<?php
/**
 * Created by PhpStorm.
 * User: liyunlong
 * Date: 2018-12-24
 * Time: 09:19
 */

namespace common\libs\swoole;


use common\helpers\Form;
use common\helpers\Log;
use common\models\forms\DeclarationLoopForm;
use console\helpers\Logger;
use yii\base\Exception;
use yii\helpers\Json;

class RPCApi
{
    public $errorCode = 0;
    public $message = '';

    private static $allowClassList = [
        '\\'.DeclarationLoopForm::class,
    ];

    public function getError(){
        $result = [
            'errorCode' => 0,
            'message' => '',
        ];
        $result['errorCode'] = $this->errorCode;
        if($this->errorCode){
            switch($this->errorCode){
                case 9001:
                    $result['message'] = '错误的包头';
                    break;
                case 9002:
                    $result['message'] = '请求包体长度超过允许的范围';
                    break;
                case 9003:
                    $result['message'] = '服务器繁忙，超过处理能力';
                    break;
                case 9204:
                    $result['message'] = '解包失败';
                    break;
                case 9205:
                    $result['message'] = '参数错误';
                    break;
                case 9206:
                    $result['message'] = '函数不存在';
                    break;
                case 9207:
                    $result['message'] = '执行错误';
                    break;
                case 9208:
                    $result['message'] = '访问被拒绝，客户端主机未被授权';
                    break;
                case 9209:
                    $result['message'] = '用户名密码错误';
                    break;
                default:
                    $result['message'] = $this->message;
            }
        }
        return $result;
    }

    /**
     * 接口
     * @param array $condition
     * @return mixed
     * @throws Exception
     */
    public static function api(array $condition)
    {
        // 记录debug日志
        Logger::trace($condition, 'rpc');
        $default = [
            //model名字
            'class' => '',
            //fields
            'fields' => [],
            //方法名
            'action' => '',
            //参数
            'param' => [],
        ];
        $condition = array_merge($default, $condition);
        if (!$condition['class']) {
            throw new Exception('Error Model Not Found ');
        }
        if (!$condition['action']) {
            throw new Exception('Error Action Not Found ');
        }
        if(!class_exists($condition['class'])){
            throw new Exception('require a class name what\'s exists ');
        }
        if(!in_array($condition['class'], self::$allowClassList)){
            throw new Exception('class is not allowed ');
        }
        $model = new $condition['class'];
        if(empty($fields))
        foreach($condition['fields'] as $key=>$field){
            if($key == 'data'){
                $model->$key = Json::encode($field);
            } else {
                $model->$key = $field;
            }
        }
        $action = $condition['action'];
        if ($condition['param']) {
            $result = $model->$action($condition['param']);
        } else {
            $result = $model->$action();
        }
        if(!$result){
            // 记录错误日志
            Logger::trace(Form::formatErrorsForApi($model->getErrors()), 'rpc');
            throw new Exception(Form::formatErrorsForApi($model->getErrors()));
        }
        // 记录结果日志
        Logger::trace($result, 'rpc');
        return $result;
    }

    /**
     * 请求
     * @param array $condition
     * @return array|null
     * @throws \yii\base\Exception
     */
    public function request(array $condition){
        $default = [
            'namespace' => '\\'.RPCApi::class.'::api',
            'param' => [],
        ];
        $condition = array_merge($default,$condition);
        if (!$condition['namespace'] || empty($condition['param'])) {
            return null;
        }
        $client = RPCClient::getInstance();
        // //$client->setEncodeType(false, true);
        // // $client->putEnv('app', 'test');
        $client->auth('test', 'ttt');//认证账号和密码
        $client->addServers(array('host' => '192.168.0.78', 'port' => 9515));
        $ret = $client->task($condition['namespace'], [$condition['param']]);
        $client->wait(10); //500ms超时
        $this->errorCode = $ret->code;
        $this->message = $ret->msg;
        return $ret->data;
    }

}