<?php
/**
 * Created by PhpStorm.
 * User: Shan
 * Date: 2017/4/1
 * Time: 17:37
 */

trait MyTrate{
    static $url  = '';
    static $OperatorID  = ''; //运营商标识
    static $OperatorSecret= '';//运营商密钥
    static $AesSecret = '';  //消息密钥
    static $AesIv = '';  //消息密钥初始化向量
    static $SigSecret ='';  //签名密钥
    static $Owner ='';  //桩属主
    static $TimeStamp ='';  //桩属主
    static $Seq ='';  //桩属主'TimeStamp', 'Seq'

    static function getTokenDate()
    {
        $datetime= date('YmdHis');
        $kk['OperatorID']= self::$OperatorID;
        $kk['OperatorSecret'] = self::$OperatorSecret;
        $en = self::encryptString(json_encode($kk));
        $sig= self::$OperatorID . $en . $datetime . "0002";
        $s= self::hmac_md5($sig);
        $rr['OperatorID'] = self::$OperatorID;
        $rr['Data']= $en;
        $rr['TimeStamp']= $datetime;
        $rr['Seq']= '0002';
        $rr['Sig'] = $s;
        $data= $rr;
        return $data;
    }
    static function getStationDate($PageNo=1)
    {
        //LastQueryTime	字符串	格式“yyyy-MM-dd HH:mm:ss”，可以为空，如果不填写，则查询所有的充电站信息
        //PageNo	整型	不填写默认为1
        //PageSize	整型	不填写默认为10
        $datetime= date('YmdHis');
        $kk['LastQueryTime']= '';
        $kk['PageNo'] =$PageNo;
        $kk['PageSize'] = 10;
        $en = self::encryptString(json_encode($kk));
        $sig= self::$OperatorID . $en . $datetime . "0002";
        $s= self::hmac_md5($sig);
        $rr['OperatorID'] = self::$OperatorID;
        $rr['Data']= $en;
        $rr['TimeStamp']= $datetime;
        $rr['Seq']= '0002';
        $rr['Sig'] = $s;
        $data= $rr;
        return $data;
    }
    static function getToken($hour)
    {
        $redis=new \Redis();
        $redis->connect('127.0.0.1',6379);
        $value=$redis->get(self::$Owner.'Token');
        if($value==false){
            $data = self::getTokenDate();
            $url  = self::$url . 'query_token';
            $da = self::CurlSend($url, $data);
            $decode = self::decryptString($da['Data']);
            $decode = json_decode($decode, true);
            $token  = $decode['AccessToken'];
            $redis->set(self::$Owner.'Token',$token,3500*$hour);
        }else{
            $token=$redis->get(self::$Owner.'Token');
        }
        return $token;
    }
    static function CurlSend($url, $data = '', $token = '')
    {
        $data    = json_encode($data);
        $ch      = curl_init();
        $headers = array();
        if ($token) {
            $headers[] = 'Authorization: Bearer ' . $token;
        }
        $headers[]   = 'Content-Type: application/json;charset=utf-8';
        $headers[]   = 'Content-Length: ' . strlen($data);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $curl_return = curl_exec($ch);
        curl_close($ch);
        return json_decode(trim($curl_return), true);
    }
    static function checkParams($params){
        $arr = ['OperatorID', 'Data', 'TimeStamp', 'Seq','Sig'];
        // 参数检查
        foreach ($arr as $v) {
            if (empty($params[$v])) {
                return $v;
            }
        }
        self::$TimeStamp=$params['TimeStamp'];
        self::$Seq=$params['Seq'];
        return 2;
    }
    /**
     * @param $OperatorID
     * @param $params
     * @return int|string
     */
    static function checkSig($OperatorID,$params){
        $sig=$OperatorID.$params['Data'].$params['TimeStamp'].$params['Seq'];
        $ecry_sig=self::hmac_md5($sig);
        if($params['Sig']!=$ecry_sig){
            return 1;
        }
        return 2;
    }
    static function fillParams($OperatorID){
        $datas=self::getParams($OperatorID);
        if(empty($datas)){
            return 1;
        }
        self::$OperatorID  = $OperatorID;
        self::$OperatorSecret= $datas['OperatorSecret'];
        self::$AesSecret = $datas['AesSecret'];
        self::$AesIv = $datas['AesIv'];
        self::$SigSecret =$datas['SigSecret'];
        self::$Owner =$datas['Owner'];
    }
    /**
     * @param $data
     * @param $ret
     * @param string $msg
     * @return string
     */
    static function encodeData($data,$ret,$msg=''){
        $data=json_encode($data);
        $data=self::encryptString($data);

        $seq=empty(self::$Seq)? '0001' : self::$Seq;
        $datetime=empty(self::$TimeStamp)? date('YmdHis') :self::$TimeStamp;

        $sig= self::$OperatorID . $data . $datetime . $seq;
        $s= self::hmac_md5($sig);

        return ['Msg'=>$msg,'Ret'=>$ret,'Data'=>$data,'Sig'=>$s];
    }
    static function getStr(){
        return Yii::$app->security->generateRandomString();
    }
    static function checkToken($token){

        $redis=Common::createRedis();
        $key='token-'.self::$Owner.'-';
        $redisToken=$redis->get($key);
        if($redisToken&&($redisToken==$token)){
            return 2;
        }
        return 1;
    }
    static function getParams($OperatorID){
        $datas=[];// $datas里面是企业信息数组
        $arr=[];
        foreach ($datas as $k=> $v){
            if($v['OperatorID']==$OperatorID){
                $arr=$datas[$k];
            }
        }
        return $arr;
    }
    static function getFile ($filename)
    {
        $ret = @file_get_contents($filename);
        return json_decode($ret, true);
    }

    /**
     * @param $log
     * @param $filename
     */
    static function setFile ($log, $filename,$append=False){
        if (!is_dir(dirname($filename))) {
            mkdir(dirname($filename), 0777, true);
            @chmod(dirname($filename), 0777);
        }
        @chmod($filename, 0777);
        if($append==true){
            file_put_contents($filename, json_encode($log)."\r\n",FILE_APPEND);
        }else{
            file_put_contents($filename, json_encode($log));
        }
    }
    static function hmac_md5($s)
    {
        $ctx = hash_init('md5', HASH_HMAC,self::$SigSecret);
        hash_update($ctx, $s);
        $rs  = hash_final($ctx);
        $rs  = strtoupper($rs);
        return $rs;
    }

    static function encryptString($input)
    {
        $size  = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $input = self::pkcs5_pad($input, $size);
        $td    = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, self::$AesSecret, self::$AesIv);
        $data  = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data  = base64_encode($data);
        return $data;
    }

    static function pkcs5_pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    static function decryptString($sStr)
    {
        mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        //$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        $iv        = self::$AesIv;
        $decrypted = @mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::$AesSecret, base64_decode($sStr), MCRYPT_MODE_CBC, $iv);
        $dec_s     = strlen($decrypted);
        $padding   = ord($decrypted[$dec_s - 1]);
        $decrypted = substr($decrypted, 0, -$padding);
        return $decrypted;
    }
    static function getCityCode(){
        $file = file(Yii::getAlias('@app').'/commands/areaCode.txt');
        $files = array();
        foreach($file as $v){
            $f = explode('    ',$v);
            //这里用trim()函数去除头尾的空格不起效果，因为是全角格式。所以用功能更强大的正则来去除空格
            $f[1] = mb_ereg_replace('^(　| )+', '', $f[1]);
            array_push($files,$f);
        }
        return $files;
    }
    static function getCityName($AreaCode,$cityCode){
        $city='';
        $pattern='/^(500)/';
        if(preg_match($pattern,$AreaCode))
            $city='重庆市';

        $pattern='/^(310)/';
        if(preg_match($pattern,$AreaCode))
            $city='上海市';

        $pattern='/^(120)/';
        if(preg_match($pattern,$AreaCode))
            $city='天津市';

        $pattern='/^(110)/';
        if(preg_match($pattern,$AreaCode))
            $city='北京市';

        $pattern='/^(4690)/';
        if(preg_match($pattern,$AreaCode)){
            $code=$AreaCode;
        }else{
            $code=substr($AreaCode,0,4).'00';
        }
        if(empty($city)){
            foreach ($cityCode as $v1){
                if($v1[0]==$code){
                    $city=$v1[1];
                }
            }
        }
        return $city;
    }
    //php5.5不支持array_column()
    static function formArr($piles){
        $arr=[];
        foreach ($piles as $v){
            $arr[]=$v['pile_id'];
        }
        return $arr;
    }
    static function insertPile($stations,$pile)
    {
        $time=time();
        $arr=[];
        foreach ($stations['StationInfos'] as $v){
            foreach ($v['EquipmentInfos'] as $v1){
                if($pile&&in_array($v1['EquipmentID'],$pile))
                    continue;
                $station_status=($v['StationStatus']==50)? 1 : 0;
                if($v1['EquipmentID'])
                    $arr[]=[$v1['EquipmentID'],self::$Owner,$v['StationID'],$v1['EquipmentType'],$time,$station_status];
            }

        }
        if($arr)
            @Yii::$app->db->createCommand()->batchInsert('pile', ['pile_id', 'owner','zhan_id','eleType','time','station_status'],
                $arr)->execute();
    }
    static function insertPic($arr=[],$id,$owner){
        $imgDir=[];
        foreach ($arr as $v){
            if($v){
                $dirInfo=self::getImage($v,$owner);
                if($dirInfo['save_path']!=2){
                    $imgDir[]=[
                        'url'=>$dirInfo['save_path'],
                        'zhan_id'=>$id,
                        'timer'=>date('Y-m-d H:i:s'),
                        'user'=>'',
                        'ischeck'=>0
                    ];
                }
            }
        }
        if($imgDir){
            Yii::$app->db->createCommand()->batchInsert(Zhanpic::tableName(), ['url','zhan_id','timer','user','ischeck'], $imgDir)->execute();
        }
    }
    static function getImage($url,$owner){
        $filename=substr($url,(strripos($url,'/')+1));
        if($filename=='default.png')
            return ['save_path'=>2];
        ob_start();
        @readfile($url);
        $img=ob_get_contents();
        ob_end_clean();
        if($img){
            $sub_dir=$owner.'/'.date('Y-m-d').'/';
            $dir=Yii::getAlias('@app').'/../uploadfile/'.$sub_dir;
            if(!file_exists($dir)){
                mkdir($dir,0777,true);
            }
            $fp2=@fopen($dir.$filename,'a');
            fwrite($fp2,$img);
            fclose($fp2);
            unset($img,$url);
            return ['save_path'=>$sub_dir.$filename];
        }else{
            return ['save_path'=>2];
        }
    }
    static function insertInfo($hour){
        $token=self::getToken($hour);
        if(!$token)
            die('token 不能为空');
        $data = self::getStationDate();

        $url = self::$url.'query_stations_info';

        $da = self::CurlSend($url, $data, $token);

        $stations=self::decryptString($da['Data']);

        $stations=json_decode($stations,true);
//        echo '<pre/>';
//        print_r($stations);
//        die();
        if($stations){
            $sql = "SELECT pile_id FROM pile  where owner=:owner ";
            $piles = Yii::$app->db->createCommand($sql, [':owner' => self::$Owner])->queryAll();
            if($piles)
                $piles=self::formArr($piles);
            self::insertPile($stations,$piles);
            $zhanList=Zhanlist::find()->select(['zhan_id'])->where(['supplier'=>self::$Owner])->asArray()->all();
            if(!empty($zhanList)){
                $aa=[];
                foreach ($zhanList as $k=>$v){
                    $aa[]=$v['zhan_id'];
                }
                $zhanList=$aa;
            }

            $cityCode=static::getCityCode();

            self::insertStation($stations,$cityCode,$zhanList);

            $page=$stations['PageCount'];
            //所有页信息
            for($i=2;$i<=$page;$i++){
                $data2=self::getStationDate($i);
                $da2 = self::CurlSend($url, $data2, $token);
                $da2=self::decryptString($da2['Data']);
                $da2=json_decode($da2,true);
                if($da2)
                    self::insertStation($da2,$cityCode,$zhanList);
                self::insertPile($da2,$piles);
            }
        }
    }
    static function padZero($str){
        $len=strlen(substr($str,strpos($str,'.')+1));
        $len=16-$len;
        for($i=0;$i<$len;$i++){
            $str.=0;
        }
        return $str;
    }
    static function pushCheck($fileName='change_status.txt'){
        $authorization=Yii::$app->request->headers->get('Authorization');
        $params=file_get_contents('php://input');
        $params=json_decode($params,true);
//        if(!empty($fileName))
//        self::writeLog($fileName,$params);
        $auths=explode(' ',trim($authorization));
        $auth=$auths[count($auths)-1];

        $checkParams=self::checkParams($params);
        if($checkParams!=2)
            return ['Msg'=>$checkParams.'为空','Ret'=>4003,'Data'=>['Status'=>1]];

        $re=self::fillParams($params['OperatorID']);
        if($re==1)
            return ['Msg'=>'OperatorID不存在','Ret'=>4003,'Data'=>['Status'=>1]];

        if($auth){
            if(self::checkToken($auth)==1)
                return self::encodeData(['Status'=>1],4002,'Token过期或者无效');
            $checkSig=self::checkSig($params['OperatorID'],$params);
            if($checkSig==1)
                return self::encodeData(['Status'=>1],4001,'签名错误');

            $data=self::decryptString($params['Data']);
            $data=json_decode($data,true);
//            if(!empty($fileName))
//            self::writeLog($fileName,$data);
            return ['code'=>200,'data'=>$data];
        }
        return self::encodeData(['Status'=>1],4002,'Bearer 未添加');
    }
    static function writeLog($name,$arr){
        if(is_array($arr)){
            if (@$_SERVER["HTTP_X_FORWARDED_FOR"])
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            else if (@$_SERVER["HTTP_CLIENT_IP"])
                $ip = $_SERVER["HTTP_CLIENT_IP"];
            else if (@$_SERVER["REMOTE_ADDR"])
                $ip = $_SERVER["REMOTE_ADDR"];
            else if (@getenv("HTTP_X_FORWARDED_FOR"))
                $ip = getenv("HTTP_X_FORWARDED_FOR");
            else if (@getenv("HTTP_CLIENT_IP"))
                $ip = getenv("HTTP_CLIENT_IP");
            else if (@getenv("REMOTE_ADDR"))
                $ip = getenv("REMOTE_ADDR");
            else
                $ip = $_SERVER['REMOTE_ADDR'];
            $pushTime=['logTime'=>date('Y-m-d H:i:s',time()),'ip'=>$ip];
            $arr=array_merge($pushTime,$arr);
            $sub_dir=date('Y-m-d');
            $dir=Yii::getAlias('@app').'/../../../'.$sub_dir.'/'.$name;
            self::setFile($arr,$dir,true);
        }
    }
    public static function initeStatus(){
        $redis=Common::createRedis();
        $datas=Zhanlist::find()->select(['zhan_id'])->where(['supplier'=>self::$Owner])->asArray()->all();
        $token=self::getToken(2);
        self::$url=self::$url.'query_station_status';
        $data=[];
        foreach ($datas as $k=>$v){
            $data[]=$v['zhan_id'];
            $i=$k+1;
            if($i%25==0){
                $dd=self::statusDate($data);
                $da = self::CurlSend(self::$url, $dd,$token);
                $decode = self::decryptString($da['Data']);
                $decode = json_decode($decode, true);
                if($decode){
                    foreach ($decode['StationStatusInfos'] as $v1){

                        foreach ($v1['ConnectorStatusInfos'] as $v2){
                            $key=self::$Owner.'--'.$v2['ConnectorID'];
                            $value=$v2['Status'];
                            $redis->set($key,$value);
                        }
                    }
                }
                $data=[];
            }
        }
        if($data){
            $dd=self::statusDate($data);
            $da = self::CurlSend(self::$url, $dd,$token);
            $decode = self::decryptString($da['Data']);
            $decode = json_decode($decode, true);
            if($decode){
                if($decode['StationStatusInfos']){
                    foreach ($decode['StationStatusInfos'] as $v1){
                        if(empty($decode['ConnectorStatusInfos']))
                            continue;
                        foreach ($v1['ConnectorStatusInfos'] as $v2){
                            $key=self::$Owner.$v2['ConnectorID'];
                            $value=$v2['Status'];
                            $redis->set($key,$value);
                        }
                    }
                }
            }
        }
    }
    public static function statusDate($id){
        $datetime= date('YmdHis');
        $kk['StationIDs']=$id;
        $en = self::encryptString(json_encode($kk));
        $sig= self::$OperatorID . $en . $datetime . "0002";
        $s= self::hmac_md5($sig);
        $rr['OperatorID'] = self::$OperatorID;
        $rr['Data']= $en;
        $rr['TimeStamp']= $datetime;
        $rr['Seq']= '0002';
        $rr['Sig'] = $s;
        return $rr;
    }
}