<?php

namespace App\Server;

class ToolServer
{
    /**
     * curl 请求工具.
     *
     * @return bool|mixed|string
     */
    public static function curl(string $method, string $url, array $params = [], bool $json = false, bool $isDecode = false)
    {
        $method = strtoupper($method);
        $ch     = curl_init();
        curl_setopt($ch, CURLOPT_HEADER, 0);
        if ('GET' == $method) {
            $url_params = '';
            foreach ($params as $key => $val) {
                if (empty($url_params)) {
                    $url_params .= '?';
                } else {
                    $url_params .= '&';
                }
                $url_params .= $key . '=' . $val;
            }
            if (!empty($url_params)) {
                $url .= $url_params;
            }
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        } elseif ('POST' == $method) {
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            if (true == $json) {
                $params  = json_encode($params, JSON_UNESCAPED_UNICODE);
                $len     = strlen($params);
                $headers = ['Content-type: application/json;charset=UTF-8', "Content-Length: $len"];
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            } else {
                $params = http_build_query($params);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        }
        $data = curl_exec($ch);
        curl_close($ch);
        if ($isDecode) {
            $data = json_decode($data, true);
        }

        return $data;
    }

    /**
     * 自动收起距离单位.
     *
     * @return float|int|string
     */
    public static function distance(float $distance)
    {
        if (-1 == $distance) {
            return -1;
        }
        if ($distance > 1000) {
            $distance = round($distance / 1000, 2) . 'km';
        } else {
            $distance .= 'm';
        }

        return $distance;
    }

    /**
     * 获取地址距离.
     *
     * @param array $from    [起点坐标(经纬度),例如:array(118.012951,36.810024)]
     * @param array $to      [终点坐标(经纬度)]
     * @param bool  $km      是否以公里为单位 false:米 true:公里(千米)
     * @param int   $decimal $decimal   精度 保留小数位数
     *
     * @return int|string 距离数值
     */
    public static function getDistance(array $from, array $to, bool $km = true, int $decimal = 2)
    {
        sort($from);
        sort($to);
        $EARTH_RADIUS = 6370.996; // 地球半径系数

        $distance = $EARTH_RADIUS * 2 * asin(sqrt(pow(sin(($from[0] * pi() / 180 - $to[0] * pi() / 180) / 2), 2) + cos($from[0] * pi() / 180) * cos($to[0] * pi() / 180) * pow(sin(($from[1] * pi() / 180 - $to[1] * pi() / 180) / 2), 2))) * 1000;

        if ($km) {
            $distance = $distance / 1000;
        }

        return round($distance, $decimal);
    }

    /**
     * 加密（可对接java）.
     *
     * @return string
     */
    public static function encodeOld(array $data, string $key, string $secret)
    {
        $plaintext = urldecode(http_build_query($data)) . '@';
        $key       = strtoupper(md5($key . $secret));
        $size      = 16;
        $iv        = str_repeat("\0", $size);
        $padding   = $size - strlen($plaintext) % $size;
        $plaintext .= str_repeat(chr($padding), $padding);
        $encrypted = openssl_encrypt($plaintext, 'AES-192-CBC', base64_decode($key), OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

        return base64_encode($encrypted);
    }

    /**
     * 加密.
     *
     * @return string
     */
    public static function encode(array $data, string $key)
    {
        // 数据集合转化字符串  再加个 @
        $plaintext = urldecode(http_build_query($data)) . '@';
        // md5 加密 key
        $key_md5 = $key;
        $size    = 16;
        // 生成 16 位偏移量
        // $iv = str_repeat("\0", $size);
        $iv = '0987654321098765';
        // 使用 PKCS5Padding 填充
        $padding = $size - strlen($plaintext) % $size;
        $plaintext .= str_repeat(chr($padding), $padding);
        $encrypted = openssl_encrypt($plaintext, 'AES-128-CBC', $key_md5, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

        return base64_encode($encrypted);
    }

    public static function encodeStr(string $data, string $key)
    {
        // 数据集合转化字符串  再加个 @
        $plaintext = $data . '@';
        // md5 加密 key
        $key_md5 = $key;
        $size    = 16;
        // 生成 16 位偏移量
        $iv = str_repeat("\0", $size);
        // $iv = "0987654321098765";
        // 使用 PKCS5Padding 填充
        $padding = $size - strlen($plaintext) % $size;
        $plaintext .= str_repeat(chr($padding), $padding);
        $encrypted = openssl_encrypt($plaintext, 'AES-128-CBC', $key_md5, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

        return base64_encode($encrypted);
    }

    /**
     * 解密(可对接java).
     *
     * @return array
     */
    public static function decode(string $content, string $key)
    {
        $key_md5 = $key;
        $size    = 16;
        // $iv = str_repeat("\0", $size);
        $iv          = '0987654321098765';
        $decrypted   = openssl_decrypt(base64_decode($content), 'AES-128-CBC', $key_md5, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        $data_decode = explode('@', $decrypted);

        // $data = [];
        // parse_str($data_decode[0], $data);
        return json_decode($data_decode[0], true);
    }

    /**
     * 解密（php）.
     */
    public static function decodeOld(string $content, string $key, string $secret)
    {
        $key         = strtoupper(md5($key . $secret));
        $size        = 16;
        $iv          = str_repeat("\0", $size);
        $decrypted   = openssl_decrypt(base64_decode($content), 'AES-192-CBC', base64_decode($key), OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        $data_decode = explode('@', $decrypted);

        // $data = [];
        // parse_str($data_decode[0], $data);
        // return $data;
        return json_decode($data_decode[0], true);
    }

    public static function toStr($bytes)
    {
        $str = '';
        foreach ($bytes as $ch) {
            // dd(chr($ch));
            try {
                $str .= chr($ch);
            } catch (\Exception $e) {
                dd(chr($ch));
            }
        }

        return $str;
    }

    /**
     * 签名算法.
     *
     * @return array
     */
    public static function sign(array $params, string $secret)
    {
        $p   = ksort($params);
        $str = '';
        if ($p) {
            foreach ($params as $key => $items) {
                $str .= "{$key}";
                $str .= '=';
                $str .= "{$items}";
                $str .= '&';
            }
        }
        $string = substr($str, 0, -1);
        // $string = "appKey=$this->appKey&nonce=$this->nonce&timestamp=$this->timestamp";
        $stringSignTemp = "$string&secret=$secret";
        // echo $stringSignTemp;
        $sign = strtoupper(md5($stringSignTemp));

        $params['sign'] = $sign;

        return $params;
    }
}
