<?php

namespace SRVX\Api\Controllers;

use SRVX\Model\SysModule;
use SRVX\Msg;
use Phalcon\Logger;
use SRVX\Utils\Common;
use Phalcon\Logger\Adapter\Stream;
use App\constants\Common as ICommon;

/**
 * Class ControllerBase
 * @package SRVX\Api\Controllers
 * @property \Phalcon\Tag $tag
 * @property \Phalcon\Http\Response\Cookies $cookies
 * @property \Phalcon\Escaper $escaper
 * @property \SRVX\Service $s
 * @property \Redis $redis
 * @property \Phalcon\Session\Manager $session
 * @property \Phalcon\Config $config
 * @property \Phalcon\Cache $cache
 */
class ControllerBase extends \Phalcon\Mvc\Controller
{

    protected $limit = 20;
    protected $offset = 0;
    protected $postAction = [];
    protected $userInfo = [];

    public function onConstruct()
    {
        $this->request->isOptions() && (header('HTTP/2.0 204 NO CONTENT') || die);

        // 只允许POST的操作
        if (!$this->request->isPost() && $this->postAction && in_array($this->dispatcher->getActionName(), $this->postAction)) {
            die();
        }
    }

    public function output($code = 0, $msg = null, $data = null)
    {
        throw new \Exception($msg, $code);
    }

    public function beforeExecuteRoute()
    {
        if (in_array($_SERVER["REQUEST_URI"], ICommon::WHITE_URL)) {
            $this->userInfo = [];
            return true;
        }
    }

    public function afterExecuteRoute()
    {

    }


    /**
     * 初始化信息
     */
    public function initialize()
    {
        $this->limit();
        $this->offset();
    }

    public function getRawData($useArray = false)
    {
        $res = !$this->request->isPost() && !$this->request->isPut() && $this->request->isPatch() && !$this->request->isDelete() ? $this->api(Msg::ErrNotFound) : json_decode(file_get_contents('php://input'), $useArray);

        // return $res ?? $this->api(Msg::ErrInvalidArgument);
        return $res ?? [];
    }

    /**
     * 输出信息并退出程序
     * @param mixed $data
     * @param int $count
     * @param bool $urlDecodeFlag
     */
    public function api($data = Msg::Suc, $count = null, $urlDecodeFlag = false)
    {
        $preContent = ob_get_contents();
        $preContent && die;
        $data === true && $data = Msg::Suc;
        $data === false && $data = Msg::ErrFailure;
        $res = is_array($data) && isset($data['statusCode'], $data['code'], $data['msg']) ? [
            'code' => $data['code'],
            'msg'  => $data['msg'],
            'data' => [],
        ] : ['code' => 0, 'msg' => '', 'data' => $data];
        $count !== null && ($res['count'] = $count);
        header('Content-type:application/json;charset=utf-8');
        is_array($data) && isset($data['statusCode']) && header('HTTP/2.0 ' . $data['statusCode']);
        die($urlDecodeFlag ? urldecode(json_encode($res, 320)) : json_encode($res, 320));
    }


    /**
     * 重定向uri
     * @param string $uri 'controller/action'
     */
    protected function forward($uri)
    {
        $uriParts = explode('/', $uri);
        $params   = array_slice($uriParts, 2);
        $this->dispatcher->forward(['controller' => $uriParts[0], 'action' => $uriParts[1], 'params' => $params,]);
    }

    /**
     * filter $_GET request
     * @param int $setLimit
     * @return array
     */
    protected function getQuery($setLimit = 0)
    {
        $get = $this->request->getQuery();
        unset($get['_url']);
        $data = [];
        foreach ($get as $k => $v) {
            $k        = htmlspecialchars($k);
            $v        = htmlspecialchars($v);
            $data[$k] = $v;
        }

        if ($setLimit) {
            $data['limit'] = $data['limit'] ?? $this->limit;
            $data['limit'] > 1000 && $data['limit'] = 1000;
        }
        return $data;
    }

    /**
     * 过滤字符串
     * @param $str
     * @return mixed
     */
    protected function _trim($str)
    {
        return trim(preg_replace('/^　+|　+$/ ', ' ', preg_replace('/( |　|\r\n|\r|\n)+/', ' ', $str)));
    }


    /**
     * [返回每页条数]
     * @return [type]      [description]
     */
    public function limit()
    {
        if ($this->request->isPost()) {
            $pageNum = $this->getRawData('limit')['limit'] ?? '';
        } else {
            $pageNum = $this->request->get('limit');
        }
        if (!empty($pageNum)) {
            $this->limit = $pageNum;
        }
    }

    /**
     * [返回偏移量]
     * @return [type]      [description]
     */
    public function offset()
    {
        if ($this->request->isPost()) {
            $page = $this->getRawData('p')['p'] ?? '';
        } else {
            $page = $this->request->get('p');
        }

        if (!empty($page)) {
            $this->offset = ($page - 1) * $this->limit;
        }
    }

    /**
     * 记录日志
     * @param        $msg
     * @param string $name
     * @param bool $mode
     */
    public function logger($msg, $name = 'debug', $mode = false)
    {
        //开启了debug模式才记录日志
        if (DEBUG) {
            $time = time();
            if (file_exists(DIR_LOG)) {
                $path   = DIR_LOG . date('Y_m_d', $time) . '_' . $name . '.log';
                $logger = new Logger('messages', ['main' => new Stream($path),]);
                $msg    = is_array($msg) ? json_encode($msg, 320) : $msg;
                $ip     = Common::getRealIP() ? Common::getRealIP() : ' IP NULL ';
                $msg    = $ip . ' ' . $msg;
                $logger->debug($msg);
            } else {
                if ($mode) {
                    return;
                }
                @mkdir(DIR_LOG, 0755, true);
                $this->logger($msg, $name, true);
            }
        }
    }


    /**
     * [校验参数]
     * @param  [type] $key  [description]
     * @param  [type] $args [description]
     * @return [type]       [description]
     */
    protected function checkParams($argsKey, $args)
    {
        if (empty($args)) {
            $this->api(Msg::ErrParameterCannotBeNull);
        }

        if (empty($argsKey)) {
            $this->api(Msg::NewError(400, 'check params value is null'));
        }


        foreach ($argsKey as $key => $value) {
            if (!array_key_exists($key, $args)) {
                $this->api(Msg::NewError(400, '【' . $key . '】 not null'));
            } else {
                switch ($value) {
                    case 'array':
                        if (!is_array($args[$key])) {
                            $this->api(Msg::NewError(400, '【' . $key . '】 not object'));
                        }
                        break;

                    case 'numeric':
                        if (!is_numeric($args[$key])) {
                            $this->api(Msg::NewError(400, '【' . $key . '】 not numeric'));
                        }
                        break;

                    default:
                        if (!is_string($args[$key])) {
                            $this->api(Msg::NewError(400, '【' . $key . '】 not string'));
                        }
                        break;
                }
            }
        }
    }

}