<?php
/**
 * Link         :   http://www.phpcorner.net
 * User         :   qingbing<780042175@qq.com>
 * Date         :   2018-11-07
 * Version      :   1.0
 */

namespace Helper;

class Unit
{
    /**
     * 获取对象的反射类
     * @param object $object
     * @return \ReflectionClass
     * @throws \ReflectionException
     */
    public static function getReflectionClass($object)
    {
        return new \ReflectionClass($object);
    }

    /**
     * 创建一个实例
     * @param array|string $config
     * @return mixed
     * @throws Exception
     * @throws \ReflectionException
     */
    public static function createObject($config)
    {
        if (!is_array($config)) {
            $config = ['class' => $config];
        }
        if (!isset($config['class'])) {
            throw new Exception('创建类实例配置中必须包含"class"元素', 100100401);
        }

        $className = $config['class'];
        unset($config['class']);

        if (($n = func_num_args()) > 1) {
            $args = func_get_args();
            $class = new \ReflectionClass($className);
            unset($args[0]);
            // Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+
            // $object=$class->newInstanceArgs($args);
            $object = call_user_func_array([$class, 'newInstance'], $args);
        } else {
            $object = new $className;
        }
        // 设置对象属性
        $object->configure($config);
        // 如果存在init函数，在 new 以后就执行
        if (method_exists($object, 'init')) {
            $object->init();
        }
        return $object;
    }

    /**
     * 合并数组
     * @return array|mixed
     */
    public static function mergeArray()
    {
        $args = func_get_args();
        $res = array_shift($args);
        while (!empty($args)) {
            $next = array_shift($args);
            foreach ($next as $k => $v) {
                if (is_integer($k)) {
                    $res[] = $v;
                } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
                    $res[$k] = self::mergeArray($res[$k], $v);
                } else {
                    $res[$k] = $v;
                }
            }
        }
        return $res;
    }

    /**
     * 判断是否是一个合法的日期构成
     * @param int $year
     * @param int $month
     * @param int $date
     * @return bool
     */
    static public function isValidDate($year, $month, $date)
    {
        return checkdate($month, $date, $year);
    }

    /**
     * 判断是否是一个合法的时间构成
     * @param int $hour
     * @param int $min
     * @param int $sec
     * @param bool $hs24 whether the hours should be 0 through 23 (default) or 1 through 12.
     * @return bool
     */
    static public function isValidTime($hour, $min, $sec, $hs24 = true)
    {
        if ($hs24 && ($hour < 0 || $hour > 23) || !$hs24 && ($hour < 1 || $hour > 12)) return false;
        if ($min > 59 || $min < 0) return false;
        if ($sec > 59 || $sec < 0) return false;
        return true;
    }

    /**
     * 创建格林时间戳
     * @param int $hour
     * @param int $min
     * @param int $sec
     * @param bool $mon
     * @param bool $day
     * @param bool $year
     * @param bool $is_gmt
     * @return int|float
     */
    static public function getTimestamp($hour, $min, $sec, $mon = false, $day = false, $year = false, $is_gmt = false)
    {
        if ($mon === false) {
            return $is_gmt ? @gmmktime($hour, $min, $sec) : @mktime($hour, $min, $sec);
        }
        return $is_gmt ? @gmmktime($hour, $min, $sec, $mon, $day, $year) : @mktime($hour, $min, $sec, $mon, $day, $year);
    }

    /**
     * 获取一个年份的 full-year
     * @param int $year
     * @return int
     */
    public static function getFullYear($year)
    {
        is_string($year) && ($year = (int)$year);
        if ($year < 100) {
            $yr = (int)date("Y");
            $century = (int)($yr / 100);
            if ($yr % 100 > 50) {
                $c1 = $century + 1;
                $c0 = $century;
            } else {
                $c1 = $century;
                $c0 = $century - 1;
            }
            $c1 *= 100;
            // if 2-digit year is less than 30 years in future, set it to this century
            // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
            if (($year + $c1) < $yr + 30) {
                $year = $year + $c1;
            } else {
                $year = $year + $c0 * 100;
            }
        }
        return $year;
    }

    /**
     * 内存单位转换 memory-capacity
     * @param $size
     * @param string $targetUnit
     * @param string $sourceUnit
     * @return null|string
     */
    static public function switchMemoryCapacity($size, $targetUnit = 'KB', $sourceUnit = 'B')
    {
        $supportUnit = [
            'B' => 1,
            'KB' => 2,
            'MB' => 3,
            'GB' => 4,
            'TB' => 5,
        ];
        $targetUnit = strtoupper($targetUnit);
        if (!isset($supportUnit[$targetUnit])) {
            return null;
        }
        if (is_numeric($size)) {
            $size = floatval($size);
            $sourceUnit = strtoupper($sourceUnit);
        } else {
            $size = strtoupper($size);
            if (preg_match('#^(\d*(\.\d*)?)(.*)$#', $size, $m)) {
                $size = $m[1];
                $sourceUnit = $m[3];
                if (!isset($supportUnit[$sourceUnit])) {
                    return "0 {$targetUnit}";
                }
            } else {
                return "0 {$targetUnit}";
            }
        }
        return round($size * pow(1024, $supportUnit[$sourceUnit] - $supportUnit[$targetUnit]), 3) . " {$targetUnit}";
    }
}