<?php

namespace Heanup\Frame;

abstract class Controller
{
    protected $tpl; // 模板路径, 可选
    protected $queryObj;
    protected $data_name = false;
    protected $isrestful = false;

    final public function __construct()
    {
        $this->queryObj = $this->getQuery();
    }

    /**
     * 主逻辑
     */
    final public function run()
    {
        try {
            $this->before();
            $method = strtolower($_SERVER['REQUEST_METHOD']);
            if ($method == 'options') {
                $this->optionsData();
            }
            $this->checkAuth();
            $data_name = $method . 'Data';
            if ($this->isrestful) {
                if (!method_exists(get_called_class(), $data_name)) {
                    Response::sendResponse(405, ['method' => strtoupper($method)], 'Method not allowed');
                    die();
                }
                $this->$data_name();
            } else {
                $this->main();
            }
        } catch (\Exception $ex) {
            $this->showError($ex->getCode(), $ex->getMessage());
        }
    }

    public function optionsData()
    {
        header("HTTP/1.1 200");
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE");
//        header("Access-Control-Max-Age: 3");
        header("Access-Control-Allow-Headers: lang,token,content-type");
        die();

    }

    /**
     * 尽快输出结果，然后执行后续逻辑
     * 本方法的的信息不会被输出
     * 即使exit之后仍旧能被执行
     */
    final public function __destruct()
    {
        if (function_exists('fastcgi_finish_request')) {
            fastcgi_finish_request();
        }
        $this->after();
    }

    /**
     * 前置方法，处理参数
     */
    protected function before()
    {

    }

    /**
     * 执行验证
     */
    protected function checkAuth()
    {

    }

    /**
     * 执行逻辑
     */
    protected function main()
    {
    }

    /**
     * 后续方法
     */
    protected function after()
    {

    }
    /**
     * @return Filter
     */
    protected function getRequest()
    {
        static $instance = null;
        parse_str(file_get_contents('php://input'), $data);
        $data = array_merge($_POST, $_GET, $_COOKIE, $data);
        if (is_null($instance)) {
            $instance = new Filter($data);
        }
        return $instance;
    }

    /**
     * @return Filter
     */
    protected function getPut()
    {
        static $instance = null;
        try {
            $putData = file_get_contents("php://input");
            $resultData = json_decode($putData, true);
            if (is_array($resultData)) {
                //解析IOS提交的PUT数据
                $data = $resultData;
            } elseif (!strstr($putData, "\r\n")) {
                //解析本地测试工具提交的PUT数据
                parse_str($putData, $putData);
                $data = $putData;
            } else {
                //解析PHP CURL提交的PUT数据
                $putData = explode("\r\n", $putData);
                $resultData = [];
                foreach ($putData as $key => $data) {
                    if (substr($data, 0, 20) == 'Content-Disposition:') {
                        $match = explode(";", $data);
                        if (count($match) == 2) {
                            preg_match('/.*\"(.*)\"/', $data, $matchName);
                            $resultData[$matchName[1]] = $putData[$key + 2];
                        } else {
                            $info = self::parserInfo($data);
                            $file = fopen($info['tmp_name'], "r+");
                            fwrite($file, $putData[$key + 3]);
                            fclose($file);
                            $resultData[$info['field']] = $info;
                        }

                    }
                }
                $data = $resultData;
            }

        } catch (\Exception $e) {
            $data = [];
        }


        if (is_null($instance)) {
            $instance = new Filter($data);
        }
        return $instance;
    }

    private static function parserInfo($data, $options = ['saveFile' => true])
    {
        //获取参数名称, type
        $infoPattern = '/name="(.+?)"(; )?(filename="(.+?)")?/'; //todo: 待优化
        preg_match($infoPattern, $data, $matches);

        $info['field'] = $matches[1];
        $info['type'] = 'json';

        //如果是文件
        if (count($matches) > 4) {
            $info['type'] = 'file';
            $info['name'] = $matches[4];
            //如果设置保存文件, 保存到临时文件
            if (isset($options['saveFile']) && $options['saveFile']) {
                $tmpFile = tempnam(sys_get_temp_dir(), 'FD');

                $info['tmp_name'] = $tmpFile;
            }
        }

        return $info;
    }

    protected function getJson()
    {
        static $instance = null;
        $data = file_get_contents('php://input');
        $data = json_decode($data, true) ?: [];
        if (is_null($instance)) {
            $instance = new Filter($data);
        }
        return $instance;
    }

    /**
     * @return Filter
     */
    protected function getQuery()
    {
        static $instance = null;
        if (is_null($instance)) {
            $instance = new Filter($_GET);
        }
        return $instance;
    }

    protected function getFilter()
    {
        $str = $this->getQuery()->string("filter");
        $str = explode(";", $str);
        if ($str) {
            foreach ($str as $item) {
                $item = explode(":", $item);
                if ($item[1] == "") {
                    continue;
                }
                $_Filter[$item[0]] = $item[1];
            }
        }
        $_Filter['page'] = $_GET['page'] ?: ($_Filter['page'] ?: 1);
        $_Filter['pageSize'] = $_GET['pageSize'] ?: ($_Filter['pageSize'] ?: 20);
        static $instance = null;
        if (is_null($instance)) {
            $instance = new Filter($_Filter);
        }
        return $instance;
    }

    /**
     * @return Filter
     */
    protected function getPost()
    {
        static $instance = null;
        if (is_null($instance)) {
            $instance = new Filter($_POST);
        }
        return $instance;
    }

    /**
     * 获取模板, 固定模板, 与controller名称类似
     * @return Template
     */
    protected function getTemplate()
    {
        static $template;
        if ($template) {
            return $template;
        }
        $class = get_called_class();
        $class = explode('\\', $class);
        $path = dirname(__DIR__) . '/' . implode('/', array_slice($class, 1, 2)) . '/Template/';
        if (!$this->tpl) {
            $this->tpl = implode('/', array_slice($class, 4));
        }
        $template = new Template();
        $template->setPath($path)->setTpl($this->tpl);
        $data = get_object_vars($this);
        if ($data) {
            $template->assign($data);
        }
        return $template;
    }

    /**
     * 检查CSRF攻击
     * @return bool
     */
    protected function checkCsrf()
    {
        $host = strtolower(trim($_SERVER['HTTP_HOST']));
        $referer = parse_url($_SERVER['HTTP_REFERER']);
        $referer = substr(strtolower(trim($referer['host'])), -(strlen($host)));
        if (!empty($referer) AND $referer != $host AND $referer != ('www.' . $host)) {
            return false;
        }
        return true;
    }

}
