<?php


namespace App\Libs\Push\HuaWei\Admin;


class Application
{
    private $appid;

    private $appsecret;

    private $token_expiredtime;

    private $access_token;

    private $validate_only;

    private $token_url;

    private $send_url;

    private $token_query_url;

    private $topic_sub_url;

    private $topic_unsub_url;

    private $topic_list_url;

    private $fields;


    public function __construct($appid, $appsecret)
    {
        $this->appid             = $appid;
        $this->appsecret         = $appsecret;
        $this->token_url         = config('push.server.huawei.authToken');
        $this->send_url          = config('push.server.huawei.messageSend');
        $this->token_query_url   = config('push.server.huawei.tokenQuery');
        $this->topic_sub_url     = config('push.server.huawei.topicSub');
        $this->topic_unsub_url   = config('push.server.huawei.topicUnSub');
        $this->topic_list_url    = config('push.server.huawei.topicList');
        $this->token_expiredtime = null;
        $this->accesstoken       = null;
        $this->validate_only     = false;
    }

    public function appid($value)
    {
        $this->appid = $value;
    }

    public function appsecret($value)
    {
        $this->appsecret = $value;
    }

    public function validate_only($value)
    {
        $this->validate_only = $value;
    }

    public function getApplicationFields()
    {
        $keys = [
            'appid',
            'appsecret',
            'token_url',
            'send_url',
            'token_query_url',
            'topic_sub_url',
            'topic_unsub_url',
            'topic_list_url',
            'validate_only',
            'accesstoken',
            'token_expiredtime'
        ];
        foreach ($keys as $key) {
            if (isset($this->$key)) {
                $this->fields[$key] = $this->$key;
            }
        }

        return $this->fields;
    }

    private function logPush($className, $message, $data = [])
    {
        var_dump('[' . $className . '] ' . $message, $data);
        myLog('push')->info('[HuaWei] [' . $className . '] ' . $message, compact('data'));
    }

    private function is_token_expired()
    {
        if (empty($this->accesstoken)) {
            return true;
        }
        if (time() > $this->token_expiredtime) {
            return true;
        }
        return false;
    }

    private function refresh_token()
    {
        // 请求地址
        $result = $this->curl_https_post($this->token_url, http_build_query([
            'grant_type'    => 'client_credentials',
            'client_secret' => $this->appsecret,
            'client_id'     => $this->appid
        ]), ['Content-Type: application/x-www-form-urlencoded;charset=utf-8']);
        $result = json_decode($result, true);

        // 判断
        if ($result === null || !array_key_exists('access_token', $result)) {
            $this->logPush(__FUNCTION__, 'refresh_token result error!');
            return null;
        }

        $this->logPush(__FUNCTION__, 'refresh_token result:', $result);
        $this->accesstoken       = getProp($result, 'access_token');
        $this->token_expiredtime = time() + getProp($result, 'expires_in');
        return $this->access_token;
    }

    /**
     * push_send_msg for push msg
     */
    public function push_send_msg($msg)
    {
        $body = [
            'validate_only' => $this->validate_only,
            'message'       => $msg
        ];
        $this->logPush(__FUNCTION__, 'push_send_msg body:', $body);

        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->send_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($body), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'push_send_msg result:', $result);

        return $result;
    }

    /**
     * common_send_msg for topic msg/other
     */
    public function common_send_msg($msg)
    {
        $this->logPush(__FUNCTION__, 'common_send_msg msg:', compact('msg'));
        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->send_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($msg), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'common_send_msg result:', $result);

        return $result;
    }

    /**
     * 数据控制者数据查询
     * @param $pushToken
     * @return mixed|null
     */
    public function query_push_token($pushToken)
    {
        $body = ['token' => $pushToken];
        $this->logPush(__FUNCTION__, 'query_push_token body:', $body);

        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->token_query_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($body), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'common_send_msg result:', $result);

        return $result;
    }

    /**
     * 主题订阅
     * @param       $topic
     * @param array $tokenArray
     * @return bool|mixed|string|null
     */
    public function subscribe_topic($topic, array $tokenArray)
    {
        $body = ['topic' => $topic, 'tokenArray' => $tokenArray];
        $this->logPush(__FUNCTION__, 'subscribe_topic body:', $body);

        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->topic_sub_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($body), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'subscribe_topic result:', $result);

        return $result;
    }

    /**
     * 主题退订
     * @param       $topic
     * @param array $tokenArray
     * @return bool|mixed|string|null
     */
    public function unsubscribe_topic($topic, array $tokenArray)
    {
        $body = ['topic' => $topic, 'tokenArray' => $tokenArray];
        $this->logPush(__FUNCTION__, 'unsubscribe_topic body:', $body);

        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->topic_unsub_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($body), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'unsubscribe_topic result:', $result);

        return $result;
    }

    /**
     * 主题列表
     * @param $token
     * @return bool|mixed|string|null
     */
    public function topic_list($token)
    {
        $body = ['token' => $token];
        $this->logPush(__FUNCTION__, 'topic_list body:', $body);

        if ($this->is_token_expired()) {
            $this->refresh_token();
        }

        if (empty($this->accesstoken)) {
            $this->logPush(__FUNCTION__, 'accesstoken is empty!');
            return null;
        }

        $url    = str_replace('{appid}', $this->appid, $this->topic_list_url);
        $header = ['Content-Type: application/json', "Authorization: Bearer {$this->accesstoken}"];
        $result = $this->curl_https_post($url, json_encode($body), $header);
        $result = json_decode($result, true);

        $this->logPush(__FUNCTION__, 'topic_list result:', $result);

        return $result;
    }

    private function curl_https_post($url, $data = [], $header = [])
    {
        $this->logPush(__FUNCTION__, 'curl_https_post:', compact('url', 'data'));
        $ch = curl_init($url);

        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

        // resolve SSL: no alternative certificate subject name matches target host name
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // check verify
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_POST, 1); // regular post request
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Post submit data

        $ret = @curl_exec($ch);
        if ($ret === false) {
            return null;
        }

        $info = curl_getinfo($ch);

        curl_close($ch);

        return $ret;
    }

}