<?php

namespace PhpLife\Frame;

use PhpLife\App\Admin\Config\Proxy;
use PhpLife\Library\Webp;

class Helper
{

    /*
    * 检测链接是否是SSL连接
    * @return bool
    */
    public static function isSSL()
    {
        if (!isset($_SERVER['HTTPS']))
            return false;
        if ($_SERVER['HTTPS'] === 1) {  //Apache
            return true;
        } elseif ($_SERVER['HTTPS'] === 'on') { //IIS
            return true;
        } elseif ($_SERVER['SERVER_PORT'] == 443) { //其他
            return true;
        }
        return false;
    }

    /**
     * 随机数生成器
     */
    public static function random()
    {
        return md5(microtime() . rand() . uniqid() . $_SERVER['REMOTE_ADDR']);
    }

    /**
     * 简单验证email
     * @param $email
     * @return bool
     */
    public static function validateEmail($email)
    {
        $email = trim($email);
        if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/", $email)) {
            return False;
        }
        return True;
    }

    /**
     * 检查文件是否存在
     * @todo 检查content-Type和文件大小
     * @param $url
     * @param string $extension
     * @param bool $checkHeader 检查头信息
     * @return bool
     */
    public static function validateFile($url, $extension = '', $checkHeader = false)
    {
        if (!$url) {
            return false;
        }
        $urlInfo = parse_url($url);
        if ($urlInfo['scheme'] !== 'http' && $urlInfo['scheme'] !== 'https') {
            return false;
        }
        // 检查后缀
        if ($extension) {
            $pathInfo = pathinfo($url);
            if ($pathInfo['extension'] != trim($extension, '.')) {
                return false;
            }
        }
        // 检查Http头信息
        if ($checkHeader) {
            $result = get_headers($url);
            $httpCode = explode(' ', $result[0]);
            $httpCode = $httpCode[1];
            if ($httpCode != 200) {
                return false;
            }
        }
        return true;
    }

    /**
     * 对象转换
     * @param object $target
     * @param object $source
     * @return object
     */
    public static function objectMerge($target, $source)
    {
        if (!is_object($target)) {
            return null;
        }
        $result = clone $target;
        $source = (array)$source;
        foreach ($source as $k => $v) {
            $result->{$k} = $v;
        }
        return $result;
    }

    /**
     * 去除首尾全角及半角空格,多个空格合并为一个
     * @param type $str
     * @return string
     */
    public static function trimAndMerge($str)
    {
        $str = preg_replace('/( |　)+/', ' ', $str);
        return trim(preg_replace("/^　+|　+$/ ", " ", $str));
    }

    /**
     * 去除首尾空格,包含全角空格
     */
    public static function trim($str)
    {
        //$str = trim($str,"　 \t\n\r\0\x0B");
        $str = mb_ereg_replace('(^(　| )+|(　| )+$)', '', $str);
        return $str;
    }

    /**
     * 转换为友好时间
     * @param int|string $timestamp
     * @return string
     */
    public static function convertToFriendlyTime($timestamp)
    {
        if (!is_numeric($timestamp)) {
            $timestamp = strtotime($timestamp);
        }
        $now = time();
        $interval = abs($now - $timestamp);
        $today = strtotime(date("Ymd"));
        $tomorrow = strtotime(date("Ymd", $now + 86400));
        $thisYear = strtotime(date("Y-01-01 00:00"));
        if ($interval < 60) {
            if ($interval < 10) {
                $interval = 10;
            }
            $string = $interval . "秒前";
        } else if ($interval < 3600) {
            $string = floor($interval / 60) . '分钟前';
        } else if ($today < $timestamp AND $timestamp < $tomorrow) {
            $string = '今天' . date('H:i', $timestamp);
        } else if ($thisYear < $timestamp) {
            $string = date('n月j日', $timestamp);
        } else {
            $string = date('Y-m-d', $timestamp);
        }
        return $string;
    }

    /**
     * 写入ini文件
     * @param type $path
     * @param type $data
     * @return type
     */
    public static function writeIniFile($path, $data)
    {
        $content = null;
        foreach ($data as $key => $item) {
            if (is_array($item)) {
                $content .= "\n[{$key}]\n";
                foreach ($item as $k => $v) {
                    if (is_numeric($v) || is_bool($v)) {
                        $v = '"' . $v . '"';
                    }
                    $content .= "{$k} = {$v}\n";
                }
            } else {
                if (is_numeric($item) || is_bool($item)) {
                    $item = '"' . $item . '"';
                }
                $content .= "{$key} = {$item}\n";
            }
        }
        return file_put_contents($path, $content);
    }

    public static function checkField($input, $fileds)
    {
        $input = (array)$input;
        $output = array();
        foreach ($input as $k => $v) {
            if (in_array($k, $fileds)) {
                $output[$k] = $v;
            }
        }
        return $output;
    }

    /**
     * 递归合并数组,兼容 数字类型
     * @param array $target
     * @param mixed $source
     * @return array
     * @author daniel@danielsmedegaardbuus.dk
     * http://www.php.net/manual/zh/function.array-merge-recursive.php
     */
    public static function arrayMerge(&$target, &$source)
    {
        if (empty($target) OR !is_array($target)) {
            $target = array();
        }
        if (empty($source) OR !is_array($source)) {
            $source = array();
        }
        $merged = $target;
        foreach ($source as $key => &$value) {
            if (is_array($value) && isset($merged [$key]) && is_array($merged [$key])) {
                $merged [$key] = self::arrayMerge($merged [$key], $value);
            } else if (is_object($value) AND is_object($merged[$key])) {
                $value = (array)$value;
                foreach ($value as $k => $v) {
                    $merged [$key]->{$k} = $v;
                }
            } else {
                $merged [$key] = $value;
            }
        }
        return $merged;
    }

    /**
     * 链接添加a标签
     * @param string $content
     * @return string
     */
    public static function urlAddHref($string)
    {
        preg_match_all('@(https?://([-\w\.]+)+(:\d+)?(/([-\w/_\.]*(\?\S+)?)?)?)@', $string, $matches, PREG_SET_ORDER);
        foreach ($matches as $matche) {
            $url = $matche [0];
        }
        if ($url) {
            $newUrl = '<a href = "' . $url . '">' . $url . '</a>';
            $string = str_replace($url, $newUrl, $string);
        }
        return $string;
    }

    /**
     * 计算字符串长度，汉字按两个字符
     * @param string $str
     * @return int
     */
    public static function strlenUtf8($str)
    {
        $length = strlen(preg_replace('/[u4e00-u9fa5 ]/', '', $str));

        if ($length) {
            return strlen($str) - $length + intval($length / 3) * 2;
        } else {
            return strlen($str);
        }
    }

    public static function makeSemiangle($str)
    {
        if (!isset($str[0])) {
            return null;
        }
        $arr = array(
            '０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4',
            '５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9',
            'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D', 'Ｅ' => 'E',
            'Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I', 'Ｊ' => 'J',
            'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N', 'Ｏ' => 'O',
            'Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S', 'Ｔ' => 'T',
            'Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X', 'Ｙ' => 'Y',
            'Ｚ' => 'Z', 'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd',
            'ｅ' => 'e', 'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i',
            'ｊ' => 'j', 'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n',
            'ｏ' => 'o', 'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's',
            'ｔ' => 't', 'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x',
            'ｙ' => 'y', 'ｚ' => 'z',
            '（' => '(', '）' => ')', '〔' => '[', '〕' => ']', '【' => '[',
            '】' => ']', '〖' => '[', '〗' => ']', '“' => '[', '”' => ']',
            '‘' => '[', '’' => ']', '｛' => '{', '｝' => '}', '《' => '<',
            '》' => '>', '％' => '%', '＋' => '+', '—' => '-', '－' => '-',
            '～' => '-', '：' => ':', '。' => '.', '、' => ',', '，' => '.',
            '；' => ',', '？' => '?', '！' => '!', '…' => '-', '‖' => '|',
            '”' => '"', '’' => '`', '‘' => '`', '｜' => '|', '〃' => '"',
            '　' => ' ', '＠' => '@', '、' => '.',);
        return strtr($str, $arr);
    }

    /**
     * 获取子串，替换全角 汉字2字符，英文1字符,数字判断
     */
    public static function getUtf8SubStr($str, $len)
    {
        $str = self::makeSemiangle($str);
        return self::getRawUtf8SubStr($str, $len);
    }

    /**
     * 获取子串，不替换全角
     */
    public static function getRawUtf8SubStr($str, $len)
    {
        if ((strlen($str) + mb_strlen($str, 'UTF8')) / 2 <= $len) {
            return $str;
        } else {
            $temp_len = 0;
            $temp_str = '';
            for ($i = 0; $i < mb_strlen($str, 'UTF-8'); $i++) {
                if ($temp_len < $len) {
                    $tmp = mb_substr($str, $i, 1, 'UTF-8');
                    $temp_str .= $tmp;
                    $temp_len += ((strlen($tmp) + mb_strlen($tmp, 'UTF-8')) / 2);
                }
            }
            return $temp_str;
        }
    }

    /**
     * 从一个数组里面取出以指定key为中心的偏移, 九宫格
     */
    public static function getCenterFromList($list, $key, $length = 9)
    {
        $list = array_values($list);
        $list = array_unique($list);
        $ids = array_flip($list);
        $current = $ids[$key];
        $total = count($list);

        $first = $current - $length > 0 ? $current - $length : 0;
        $last = $current + $length < $total - 1 ? $current + $length : $total - 1;
        $limit = $last - $first + 1;

        return array_slice($list, $first, $limit);
    }

    public static function safeHtmlEncodeString($str)
    {
        $str = htmlspecialchars_decode($str);
        return htmlspecialchars($str);
    }

    /**
     * 删除数据中指定的值
     * @param max $val
     * @param array $array
     */
    public static function delArrayValue($val, $array)
    {
        $key = array_search($val, $array);
        if ($key !== false) {
            unset($array[$key]);
        }
        return array_values($array);
    }

    public static function strcut($str, $length, $etc = '...')
    {
        $result = '';
        $str = html_entity_decode(trim(strip_tags($str)), ENT_QUOTES, 'UTF-8');
        $strlen = strlen($str);

        for ($i = 0; (($i < $strlen) && ($length > 0)); $i++) {
            $number = strpos(str_pad(decbin(ord(substr($str, $i, 1))), 8, '0', STR_PAD_LEFT), '0');
            if ($number) {
                if ($length < 1.0) {
                    break;
                }
                $result .= substr($str, $i, $number);
                $length -= 1.0;
                $i += $number - 1;
            } else {
                $result .= substr($str, $i, 1);
                $length -= 0.5;
            }
        }

        $result = htmlspecialchars($result, ENT_QUOTES, 'UTF-8');

        if ($i < $strlen) {
            $result .= $etc;
        }
        return $result;
    }

    /**
     * 递归调整文件属性
     */
    public static function chmod($path, $filemode = 0755)
    {
        if (!is_dir($path)) {
            return chmod($path, $filemode);
        }
        $dh = opendir($path);
        while (($file = readdir($dh)) !== false) {
            if ($file != '.' && $file != '..') {
                $fullpath = $path . '/' . $file;
                if (is_link($fullpath)) {
                    return false;
                } elseif (!is_dir($fullpath) && !chmod($fullpath, $filemode)) {
                    return false;
                } elseif (!self::chmod($fullpath, $filemode)) {
                    return false;
                }
            }
        }
        closedir($dh);
        return chmod($path, $filemode);
    }

    /**
     * 获取服务器IP
     * @param bool $toLong 是否返回整形
     * @return string
     */
    public static function getServerIp($toLong = false)
    {
        if (isset($_SERVER['SERVER_ADDR'])) {
            $ip = $_SERVER['SERVER_ADDR'];
        } else {
            $domain = gethostname();
            $ip = gethostbyname($domain);
        }
        if ($toLong) {
            $ip = ip2long($ip);
        }
        return $ip;
    }

    /**
     * 获取客户端Ip
     * @param bool $toLong 是否返回整形
     * @return string|int
     */
    public static function getClientIp($toLong = false)
    {
        $ip = '';
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]) && $_SERVER["HTTP_X_FORWARDED_FOR"]) {
            $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } elseif (isset($_SERVER["HTTP_CLIENT_IP"]) && $_SERVER["HTTP_CLIENT_IP"]) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } elseif (isset($_SERVER["REMOTE_ADDR"]) && $_SERVER["REMOTE_ADDR"]) {
            $ip = $_SERVER["REMOTE_ADDR"];
        }
        $pos = strpos($ip, ',');
        if ($pos) {
            $ip = substr($ip, 0, $pos);
        }
        $ip = trim($ip);
        if ($toLong) {
            $ip = ip2long($ip);
        }
        return $ip;
    }

    /**
     * 获取截取后的文字
     * 英文汉字均算做一个长度
     */
    public static function getUtf8ShortCut($content, $length)
    {
        $shortCut = mb_substr($content, 0, $length, 'UTF-8');
        $shortCut = strcmp($shortCut, $content) == 0 ? $shortCut : $shortCut . '...';
        return $shortCut;
    }

    /**
     * 检查是否有http
     * @param type $str
     * @return type
     */
    public static function httpLinkChecker($str)
    {
        $reg = '/^https?/i';
        if (preg_match($reg, $str)) {
            return $str;
        } else {
            return 'http://' . $str;
        }
    }

    /**
     * 获取进程运行时间
     */
    public static function getPidTime($pid)
    {

        $i_pinfo = file_get_contents('/proc/' . $pid . '/stat');
        $args = explode(" ", $i_pinfo);
        $start_time = $args[21];

        $m_pinfo = file_get_contents('/proc/stat');
        $args = explode("\n", $m_pinfo);
        foreach ($args as $line) {
            $v = trim($line);
            if (strpos($line, "btime") !== false) {
                $args_1 = explode(" ", $v);
                $uptime = $args_1[1];
                break;
            }
        }
        if ($uptime == '' || $start_time == '') {
            return 0;
        }
        return (int)microtime(true) - (int)($uptime + $start_time / 100);
    }

    /**
     * 过滤标点符号
     * @param type $content
     * @return type
     */
    public static function strap($content)
    {
        $content = trim($content);
        $content = strip_tags($content);
        $content = preg_replace("/(&[a-zA-Z]{0,4};)/u", ' ', $content);
        $content = preg_replace("/([^a-zA-Z0-9\x{4e00}-\x{9fa5}]+)/u", ' ', $content);
        $content = trim($content);
        return $content;
    }

    public static function html2text($str)
    {
        $str = preg_replace("/<style .*?<\/style>/is", "", $str);
        $str = preg_replace("/<script .*?<\/script>/is", "", $str);
        $str = preg_replace("/<br \s*\/?\/>/i", "\n", $str);
        $str = preg_replace("/<\/?p>/i", "\n\n", $str);
        $str = preg_replace("/<\/?td>/i", "\n", $str);
        $str = preg_replace("/<\/?div>/i", "\n", $str);
        $str = preg_replace("/<\/?blockquote>/i", "\n", $str);
        $str = preg_replace("/<\/?li>/i", "\n", $str);
        $str = preg_replace("/\&nbsp\;/i", " ", $str);
        $str = preg_replace("/\&nbsp/i", " ", $str);
        $str = preg_replace("/\&amp\;/i", "&", $str);
        $str = preg_replace("/\&amp/i", "&", $str);
        $str = preg_replace("/\&lt\;/i", "<", $str);
        $str = preg_replace("/\&lt/i", "<", $str);
        $str = preg_replace("/\&ldquo\;/i", '"', $str);
        $str = preg_replace("/\&ldquo/i", '"', $str);
        $str = preg_replace("/\&lsquo\;/i", "'", $str);
        $str = preg_replace("/\&lsquo/i", "'", $str);
        $str = preg_replace("/\&rsquo\;/i", "'", $str);
        $str = preg_replace("/\&rsquo/i", "'", $str);
        $str = preg_replace("/\&gt\;/i", ">", $str);
        $str = preg_replace("/\&gt/i", ">", $str);
        $str = preg_replace("/\&rdquo\;/i", '"', $str);
        $str = preg_replace("/\&rdquo/i", '"', $str);
        $str = strip_tags($str);
        $str = preg_replace("/(\n\s*\n)+/is", "\n", $str);
        return $str;
    }

    public static function convertStringToUtf8($string)
    {
        $string = urldecode($string);
        $encoding = mb_detect_encoding($string, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5'));
        $string = mb_convert_encoding($string, 'UTF-8', $encoding);
        return $string;
    }

    /**
     * utf8多字节编码文字折行
     * @param $text
     * @param int $length
     * @return string
     */
    public static function wordwrapUtf8($text, $length = 75)
    {
        $result = array();
        $len = mb_strlen($text, 'UTF-8');
        $step = ceil($len / $length);
        for ($i = 0; $i < $step; $i++) {
            $result[] = mb_substr($text, $length * $i, $length, "UTF-8");
        }
        return implode("\n", $result);
    }


    /**
     * 从 $argv 中解析合并参数, 兼容一下情况:
     *      无前缀, 被解析成索引数组
     *      单前缀(只能是单字母, 后面可以直接跟value, 也可以空格后面跟着value,二者不能混用), 被解析成关联数组
     *      双前缀形式(可以是单字母也可以是多字母,后面必需跟着 '='), 被解析成关联数组
     * 如果不确定, 请自行打印结果查看是否正确
     * @example : php index.php first -s 'second' --third='third'
     * @return array('first', 's' => 'second', 'third' => 'third')
     */
    public static function getArguments()
    {
        $arguments = $_SERVER['argv'];
        for ($i = 0; $i < $_SERVER['argc']; $i++) {
            if (!isset($arguments[$i][0])) {
                continue;
            }

            //判断第一位是否是 '-'
            if (substr($arguments[$i], 0, 1) != '-') {
                continue;
            }

            //判断第二位是否是 '-'
            if (substr($arguments[$i], 1, 1) != '-') {
                if (strlen($arguments[$i]) == 2) {
                    $key = substr($arguments[$i], 1);
                    $value = $arguments[$i + 1];
                    $arguments[$key] = trim($value);
                    unset($arguments[$i]);
                    unset($arguments[$i + 1]);
                } elseif (strlen($arguments[$i]) > 2) {
                    $key = substr($arguments[$i], 1, 1);
                    $value = substr($arguments[$i], 2);
                    $arguments[$key] = trim($value);
                    unset($arguments[$i]);
                } else {
                    //do nothing;
                }
            } else {
                $value = substr($arguments[$i], 2);
                $value = explode('=', $value, 2);
                $arguments[$value[0]] = trim($value[1]);
                unset($arguments[$i]);
            }
        }
        return $arguments;
    }

    /**
     * 尝试解析字符串,如果解析失败则返回原值
     * @param $string
     * @return string | array
     */
    public static function jsonDecode($string)
    {
        if (!$string) {
            return $string;
        }
        $result = json_decode($string, true);
        if ($result) {
            $string = $result;
        }
        return $string;
    }

    /**
     * 获取数组分片, 从指定列表中获取指定元素之后的若干个切片
     * @param $idList
     * @param $lastId
     * @param $count
     * @return array
     */
    public static function getSlice($idList, $lastId = 0, $count = 20)
    {
        $result = array();
        if (!$idList || ($lastId && !in_array($lastId, $idList))) {
            return $result;
        }
        if ($lastId) {
            $position = array_search($lastId, $idList) + 1;
        } else {
            $position = 0;
        }
        $result = array_slice($idList, $position, $count);
        return $result;
    }
    /**
     * 创建目录
     * @param unknown $dir
     * @param number $mode
     */
    public static function mkdir($dir, $mode = 0755)
    {
        if (!is_dir($dir)) {
            $temp = explode('/', $dir);
            $cur_dir = '';
            for ($i = 0; $i < count($temp); $i++) {
                $cur_dir .= $temp[$i] . '/';
                if (!is_dir($cur_dir)) {
                    @mkdir($cur_dir, 0777);
                    @chmod($cur_dir, $mode);
                }
            }
        }
    }
    /**
     * 下载图片
     *
     * @param unknown $imgUrl
     * @return string
     */
    public static function downImg($imgUrl,$suffix=NULL)
    {
        $suffix = $suffix?:strtolower(substr(strrchr($imgUrl, '.'), 1));
        if (strlen($suffix)>5){
            $suffix="jpg";
        }
        if ($suffix==""){
            $suffix="jpg";
        }
        $new_name = "makeup/images/".date("Y-m")."/img_" . uniqid() . rand(1, 1000) . "." . $suffix;
        $path = "/www/api.test.meitu.com/" . $new_name;
        if (!is_dir("/www/api.test.meitu.com/makeup/images/".date("Y-m")."/")){
            Helper::mkdir("/www/api.test.meitu.com/makeup/images/".date("Y-m")."/");
        }
        $file=self::getContent($imgUrl);
        $i=0;
        while ($file==""&&$i<3){
            $file=self::getContent($imgUrl);
            Logger::setLog(null,'下载图片失败。原图：'.$imgUrl,'down_img_error');
            $i++;
        }
        if ($file==""){
            return "";
        }
        file_put_contents($path, $file);
        Webp::tranPic2Webp($path);//转换成webp图片
        $push = "/www/api.mgr.meitu.com/cdn/push.sh";
        push($push, $new_name);
        push($push, $new_name.'.webp');
        return "/".$new_name;
    }
    
    public static function getContent($url){
        $curlHandle = curl_init();
        curl_setopt($curlHandle, CURLOPT_URL, $url);
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, 0); // 让CURL支持HTTPS访问
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 30);
        if (strpos($url,"https")!==false){
            curl_setopt($curlHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
            curl_setopt($curlHandle, CURLOPT_PROXY, Proxy::getData("host"));
            curl_setopt($curlHandle, CURLOPT_PROXYPORT, Proxy::getData('port'));
            curl_setopt($curlHandle, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
            curl_setopt($curlHandle, CURLOPT_PROXYUSERPWD, Proxy::getData('user').":".Proxy::getData('password'));
        }
        curl_setopt($curlHandle, CURLOPT_TIMEOUT, 30);
        $file = curl_exec($curlHandle);
        curl_close($curlHandle);
        return $file;
    }

}
