<?php
/**
 * 授权基类，包含请求方式过滤 请求参数处理 请求资源限制等
 */

namespace app\api\controller;

use think\Controller;
use think\exception\HttpResponseException;
use think\Request;

class Api extends Controller
{
    use Send;

    protected $param = [];
    protected $userId;
    protected $pageIndex;
    protected $pageSize;

    /**
     * 对应操作
     * @var array
     */
    public $methodToAction = [
        'get' => 'read',
        'post' => 'save',
        'put' => 'update',
        'delete' => 'delete',
        'patch' => 'patch',
        'head' => 'head',
        'options' => 'options',
    ];

    /**
     * 允许访问的请求类型
     * @var string
     */
    public $restMethodList = 'get|post|put|delete|patch|head|options';
    /**
     * 默认不验证
     * @var bool
     */
    public $apiAuth = true;

    protected $request;

    /**
     * 当前请求类型
     * @var string
     */
    protected $method;

    /**
     * 当前资源类型
     * @var string
     */
    protected $type;

    public static $app;
    /**
     * 返回的资源类的
     * @var string
     */
    protected $restTypeList = 'json';

    /**
     * REST允许输出的资源类型列表
     * @var array
     */
    protected $restOutputType = [
        'json' => 'application/json',
    ];

    /**
     * 客户端信息
     */
    protected $clientInfo;

    /**
     * 控制器初始化操作
     */

    public function _initialize()
    {
        $request = Request::instance();
        $this->request = $request;
        $this->init();    //检查资源类型
    }

    public function __construct(Request $request = null)
    {
        parent::__construct();
        $this->param = $request->param();
        $this->getPageIndexAndSize();
    }

    /**
     * 初始化方法
     * 检测请求类型，数据格式等操作
     */
    public function init()
    {
        $request = Request::instance();

        $ext = $request->ext();
        if ('' == $ext) {
            // 自动检测资源类型
            $this->type = $request->type();
        } elseif (!preg_match('/\(' . $this->restTypeList . '\)$/i', $ext)) {
            // 资源类型非法 则用默认资源类型访问
            $this->type = $this->restDefaultType;
        } else {
            $this->type = $ext;
        }
        $this->setType();
        // 请求方式检测
        $method = strtolower($request->method());
        $this->method = $method;
        if (false === stripos($this->restMethodList, $method)) {
            throw new HttpResponseException(json((object)array('error'=>405,'message'=>'No routing path can be found for the request.'),200));
        }
    }

    /**
     * 空操作
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Xml
     */
    public function _empty()
    {
        return $this->render(200);
    }

    /**
     * 单个参数验证
     *
     * @param $value
     * @param $key
     * @param $validate
     */
    protected function checkSingle($value, $key, $validate)
    {
        $this->check([$key => $value], $validate);
    }

    /**
     * 验证参数
     * @access protected
     * @param array $data 数据
     * @param string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     */
    protected function check($data, $validate, $message = [])
    {
        $validateResult = $this->validate($data, $validate, $message);
        if ($validateResult !== true) {
            self::returnmsg(403, [], [], "", "param error", $validateResult);
        }
    }

    /**
     * 获取页码和每页数量
     * @param int $defaultIndex
     * @param int $defaultSize
     * @param int $sizeLimit
     */
    protected function getPageIndexAndSize($defaultIndex = 1, $defaultSize = 20, $sizeLimit = 1000)
    {
        $this->pageIndex = isset($this->param['page_index']) ? $this->param['page_index'] : null;
        $this->pageSize = isset($this->param['page_size']) ? $this->param['page_size'] : null;
        $this->pageIndex = $this->pageIndex ?: $defaultIndex;
        $this->pageSize = $this->pageSize ?: $defaultSize;

        $this->checkSingle($this->pageIndex, 'page_index', 'Base.page_index');
        $this->checkSingle($this->pageSize, 'page_size', 'Base.page_size');

        if ($this->pageSize > $sizeLimit) {
            self::returnmsg(403, [], [], "", "param error", "参数不合法");
        }
    }

    /**
     * 获取指定参数
     *
     * @param string $key
     * @param mixed|null $defaultValue
     * @return mixed|null
     */
    protected function getParam($key, $defaultValue = null)
    {
        return isset($this->param[$key])
            ? (is_string($this->param[$key]) ? trim($this->param[$key]) : $this->param[$key])
            : $defaultValue;
    }

    /**
     * 获取多个参数，keysArray为空时获得全部参数
     * 注意键名不能为数字
     *
     * @param array|null $keysArray
     * @return array
     */
    protected function selectParam($keysArray = null)
    {
        if ($keysArray) {
            $paramResult = [];
            foreach ($keysArray as $key => $value) {
                if (is_int($key)) {
                    // 没有 key , 用数字作为key
                    $paramResult[$value] = $this->getParam($value);
                } else {
                    // 有 key 和 value , value为参数默认值
                    $paramResult[$key] = $this->getParam($key, $value);
                }
            }
            return $paramResult;
        } else {
            return $this->param;
        }
    }
}