<?php


namespace file;


class FileSystem
{
    /**
     * @var string
     */
    private static $rootPath;
    /**
     * @var string
     */
    private static $appPath;
    /**
     * @var string
     */
    private static $runtimePath;

    /**
     * 获取文件名
     * @param $file
     * @return array
     */
    public static function getFileName($file)
    {
        return explode('.', basename($file))[0];
    }

    /**
     * 获取文件扩展名
     * @param $file
     * @return array
     */
    public static function getFileExt($file)
    {
        return explode('.', basename($file))[1];
    }

    /**
     * 获取应用根目录
     * @return string
     */
    public static function getRootPath()
    {
        if(!self::$rootPath) {
            if ('cli' == PHP_SAPI) {
                $scriptName = realpath($_SERVER['argv'][0]);
            } else {
                $scriptName = $_SERVER['SCRIPT_FILENAME'];
            }

            $path = realpath(dirname($scriptName));
            if (!is_file($path . DIRECTORY_SEPARATOR . 'command')) {
                $path = dirname($path);
            }
            self::$rootPath = $path . DIRECTORY_SEPARATOR;
        }
        return self::$rootPath;
    }

    /**
     * 获取应用目录
     * @return string
     */
    public static function getAppPath()
    {
        if(!self::$appPath){
            self::$appPath = self::getRootPath() . 'app' . DIRECTORY_SEPARATOR;
        }
        return self::$appPath;
    }

    /**
     * 获取运行时目录
     * @return string
     */
    public static function getRuntimePath()
    {
        if(!self::$runtimePath){
            self::$runtimePath = self::getRootPath() . 'runtime' . DIRECTORY_SEPARATOR;
        }
        return self::$runtimePath;
    }

    /**
     * 搜索文件
     * @param $path
     * @param string $type
     * @return array
     */
    public static function scanFile($path, $type = null)
    {
        $result = array();
        $files = scandir($path);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                if (is_dir($path . '/' . $file)) {
                    $result[$file] = self::scanFile($path . '/' . $file);
                } elseif ($type && explode('.', $file)[1] == $type) {
                    $result[] = $path . '/' . $file;
                } elseif (!$type){
                    $result[] = $path . '/' . $file;
                }
            }
        }
        return $result;
    }

    /**
     * 保存文件
     * @param $filename
     * @param $data
     * @return false|int
     */
    public static function saveFile($filename, $data = '')
    {
        $dir = substr($filename,'0',strrpos($filename,'/'));
        if (!file_exists($dir)) {
            mkdir($dir, 777, true);
        }
        return file_put_contents($filename, json_encode($data));
    }

    /**
     * 清空目录文件
     * @param $dir
     * @param null $type
     */
    public static function clearDir($dir,$type = null){
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                if (is_dir($dir . '/' . $file)) {
                    self::clearDir($dir . '/' . $file);
                    @rmdir($dir . '/' . $file);
                } else {
                    @unlink($dir . '/' . $file);
                }
            }
        }
    }

    /**
     * 读取文件某一行记录
     * @param $file
     * @param $line
     * @return bool|false|string
     */
    public static function getFileLine($file, $line)
    {
        $n = 0;
        $handle = fopen($file, 'r');
        if ($handle) {
            while (!feof($handle)) {
                ++$n;
                $out = fgets($handle, 4096);
                if ($line == $n) break;
            }
            fclose($handle);
        }
        if ($line == $n) {
            $encode = mb_detect_encoding($out, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
            $str = mb_convert_encoding($out, 'UTF-8', $encode);
            return $str;
        }
        return false;
    }

    /**
     * 文件追加写入
     * @param $file
     * @param $content
     * @param bool $is_new_line
     * @return false|int
     */
    public static function appendWriteFile($file,$content,$is_new_line = true){
        if($is_new_line){
            $content .= PHP_EOL;
        }
        $handle = fopen($file, "a");
        $ret = fwrite($handle, $content);
        fclose($handle);
        return $ret;
    }

    /**
     * 获取文本文件行数
     * @param $filename
     * @param string $ending
     * @return int
     */
    public static function getTxtFileLines($filename, $ending = PHP_EOL)
    {
        $fp = fopen($filename, 'r');
        $lines = 0;
        while (stream_get_line($fp, filesize($filename),$ending)) {
            $lines++;
        }
        fclose($fp);
        return $lines;
    }

    /**
     * 块级读取文件记录
     * @param $file
     * @param int $start
     * @param int $end
     * @param string $callback
     * @return array
     * @throws \Exception
     */
    public static function getFileBlockData($file, $start = 0, $end = 0, $callback = '')
    {
        $n = 0;
        $data = [];
        $handle = fopen($file, 'r');
        if (!$handle) {
            throw new \Exception('文件'.$file.'不存在');
        }
        $start = $start >=0 ? $start: 0;
        if($end !=0 && $start > $end){
            $temp = $start;
            $start = $end;
            $end = $start;
        }
        while (!feof($handle)) {
            ++$n;
            $str = fgets($handle, 4096);
            if ($start <= $n && trim($str) != '') {
                $encode = mb_detect_encoding($str, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5'));
                if($encode){
                    $str = mb_convert_encoding($str, 'UTF-8', $encode);
                }else {
                    $str = mb_convert_encoding($str, 'UTF-8');
                }
                if($callback){
                    $data[] = call_user_func($callback, $str);
                }else {
                    $data[] = $str;
                }
            }
            if ($end == $n) break;
        }
        fclose($handle);
        return $data;
    }
}