<?php
/**
 * Controller
 */
Class Controller {
    protected $layout = 'main';

    function __construct() {
        //set default layout
        if (!empty(FSC::$app['config']['default_layout'])) {
            $this->layout = FSC::$app['config']['default_layout'];
        }

        //json body auto serialization to $_POST
        try {
            $json = file_get_contents('php://input');
            $jsonData = json_decode($json, true);

            if (!empty($jsonData)) {
                $_POST = array_merge($_POST, $jsonData);
            }
        }catch(Exception $e) {}
    }

    function __destruct() {
        $this->logTimeCost();
    }

    //redirect url
    protected function redirect($url, $code = 302) {
        header("Location: {$url}", true, $code);
        exit;
    }

    //render view
    protected function render($viewName, $viewData = array(), $pageTitle = '') {
        $baseLayoutFile = $themeLayoutFile = $layoutFile = '';
        $baseViewFile = $themeViewFile = $viewFile = '';

        $baseLayoutFile = __DIR__ . '/../views/layout/' . $this->layout . '.php';
        $baseViewFile = __DIR__ . '/../views/' . FSC::$app['controller'] . '/' . $viewName . '.php';
        //双斜杠//开头的共享视图支持
        if (preg_match('/^\/\//', $viewName)) {
            $baseViewFile = __DIR__ . '/../views/' . str_replace('//', '/', $viewName) . '.php';
        }

        if (!empty(FSC::$app['config']['theme'])) {
            $themeLayoutFile = __DIR__ . '/../themes/' . FSC::$app['config']['theme'] . '/views/layout/' . $this->layout . '.php';
            $themeViewFile = __DIR__ . '/../themes/' . FSC::$app['config']['theme'] . '/views/' . FSC::$app['controller'] . '/' . $viewName . '.php';
            //双斜杠//开头的共享视图支持
            if (preg_match('/^\/\//', $viewName)) {
                $themeViewFile = __DIR__ . '/../themes/' . FSC::$app['config']['theme'] . '/views/' . 
                            str_replace('//', '/', $viewName) . '.php';
            }
        }

        if (!empty($themeLayoutFile) && file_exists($themeLayoutFile)) {
            $layoutFile = $themeLayoutFile;
            $viewFile = $themeViewFile;
        }else if (file_exists($baseLayoutFile)) {
            $layoutFile = $baseLayoutFile;
            $viewFile = $baseViewFile;
        }

        //include layout and view
        if (!empty($layoutFile)) {
            ob_start();
            include_once $layoutFile;

            $htmlCode = ob_get_contents();
            ob_end_clean();

            //enable gzip
            ob_start('ob_gzhandler');

            //show time cost
            $end_time = microtime(true);
            $page_time_cost = ceil( ($end_time - FSC::$app['start_time']) * 1000 );   //ms
            echo str_replace('{page_time_cost}', $page_time_cost, $htmlCode);

            ob_end_flush();
        }else {
            $error_message = "Layout file {$this->layout}.php is not exist.";
            if (!empty(FSC::$app['config']['theme'])) {
                $error_message = "Layout file {$this->layout}.php in theme " . FSC::$app['config']['theme'] . " is not exist.";
            }
            throw new Exception($error_message, 500);
        }
    }

    //render json data
    protected function renderJson($data, $httpStatus = 200, $headers = array()) {
        if (!empty(FSC::$app['config']['debug'])) {
            $end_time = microtime(true);
            $data['page_time_cost'] = ceil( ($end_time - FSC::$app['start_time']) * 1000 );   //ms
        }

        header("Content-Type: application/json; charset=utf-8");
        if ($httpStatus != 200 && is_numeric($httpStatus)) {
            $title = "HTTP/1.0 {$httpStatus} Internal Server Error";
            switch($httpStatus) {
                case 304:
                    $title = "HTTP/1.0 {$httpStatus} Not Modified";
                    break;
                case 401:
                    $title = "HTTP/1.0 {$httpStatus} 未授权";
                    break;
                case 402:
                    $title = "HTTP/1.0 {$httpStatus} 未购买";
                    break;
                case 403:
                    $title = "HTTP/1.0 {$httpStatus} 禁止访问";
                    break;
                case 404:
                    $title = "HTTP/1.0 {$httpStatus} 不存在";
                    break;
                case 500:
                    $title = "HTTP/1.0 {$httpStatus} 系统错误";
                    break;
            }

            header($title, true, $httpStatus);
        }

        if (!empty($headers)) {
            foreach($headers as $item) {
                header($item);
            }
        }

        echo json_encode($data);
        exit;
    }

    //render m3u8 file
    protected function renderM3u8($content) {  
        header("Content-Type: application/x-mpegURL; charset=utf-8");
        echo $content;
        exit;
    }

    //get params by key
    protected function get($key = '', $defaultValue = '') {
        if (empty($key)) {
            return $_GET;
        }
        return !empty($_GET[$key]) ? $_GET[$key] : $defaultValue;
    }

    //post params by key
    protected function post($key = '', $defaultValue = '') {
        if (empty($key)) {
            return $_POST;
        }
        return !empty($_POST[$key]) ? $_POST[$key] : $defaultValue;
    }

    //debug log
    protected function logTimeCost() {
        if (!empty(FSC::$app['config']['debug'])) {
            $end_time = microtime(true);
            $timeCost = ceil( ($end_time - FSC::$app['start_time']) * 1000 );   //ms
            $thisUrl = FSC::$app['requestUrl'];
            $logTime = date('Y-m-d H:i:s');
            $logDir = __DIR__ . '/../runtime/logs/';
            $logOk = @error_log("{$logTime}\t{$thisUrl}\ttime cost: {$timeCost} ms\n", 3, "{$logDir}debug.log");
            if (!$logOk) {      //try to mkdir
                @mkdir($logDir, 0700, true);
                @error_log("{$logTime}\t{$thisUrl}\ttime cost: {$timeCost} ms\n", 3, "{$logDir}debug.log");
            }
        }
    }

    //error log
    protected function logError($error_message) {
        $thisUrl = FSC::$app['requestUrl'];
        $logTime = date('Y-m-d H:i:s');
        $logDir = __DIR__ . '/../runtime/logs/';
        $logFilename = 'error.log';
        $logOk = @error_log("{$logTime}\t{$thisUrl}\tERROR: {$error_message}\n", 3, "{$logDir}{$logFilename}");
        if (!$logOk) {      //try to mkdir
            @mkdir($logDir, 0700, true);
            @error_log("{$logTime}\t{$thisUrl}\tERROR: {$error_message}\n", 3, "{$logDir}{$logFilename}");
        }
    }

    //get user real ip
    protected function getUserIp() {
        $ip = false;

        if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        }

        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ips = explode(', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
            if (!empty($ip)) {
                array_unshift($ips, $ip);
                $ip = false;
            }

            if (!empty($ips)) {
                for ($i = 0; $i < count($ips); $i++) {
                    if (!preg_match("/^(10|172\.16|192\.168)\./", $ips[$i])) {
                        $ip = $ips[$i];
                        break;
                    }
                }
            }
        }

        return !empty($ip) ? $ip : $_SERVER['REMOTE_ADDR'];
    }

    //request url via curl
    protected function request(
        $url, $postFields = array(), $timeout = 10, $pc = false, $options = array()
    ) {
        $s = curl_init();

        curl_setopt($s, CURLOPT_URL, $url);
        curl_setopt($s, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($s, CURLOPT_RETURNTRANSFER, true);

        if (!empty($postFields)) {
            curl_setopt($s, CURLOPT_POST, true);
            curl_setopt($s, CURLOPT_POSTFIELDS, $postFields);
        }

        if (!empty($options)) {
            curl_setopt( $s, CURLOPT_HTTPHEADER, $options);
        }

        //iphone client
        $user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
        //mac os client
        if ($pc) {
            $user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36';
        }
        curl_setopt($s, CURLOPT_USERAGENT, $user_agent);
        curl_setopt($s, CURLOPT_REFERER, '-');

        $curlResult = curl_exec($s);
        $curlStatus = curl_getinfo($s, CURLINFO_HTTP_CODE);
        curl_close($s);

        return array(
            'status' => $curlStatus,
            'result' => $curlResult,
        );
    }

    //set cookie for message show
    //type: info, warning, danger, success
    protected function sendMsgToClient($msg, $type = 'info') {
        $cookieKey = "alert_msg_{$type}";
        $expires = time() + 15;
        $path = '/';

        //empty character replace to "%20"
        $encoded = urlencode($msg);
        $noempty = str_replace('+', '%20', $encoded);
        $val = base64_encode( $noempty );

        setcookie($cookieKey, $val, $expires, $path);
    }

    //sort menus and dirTree
    protected function sortMenusAndDirTree($menus_sorted, $menus, $dirTree) {
        if (empty($menus_sorted) || empty($menus) || empty($dirTree)) {return false;}

        //一级目录菜单排序
        $menu_dirs = array_column($menus, 'directory');
        $names = array_replace(array_flip($menus_sorted), array_flip($menu_dirs));
        if (!empty($names)) {
            $menus_sorted = array_keys($names);

            $arr = array();
            foreach($menus_sorted as $name) {
                $index = array_search($name, $menu_dirs);
                array_push($arr, $menus[$index]);
            }
            $menus = $arr;
        }

        //dirTree一级目录排序
        $sorted_dirs = array_column($menus, 'directory');
        $tree_dirs = array_column($dirTree, 'directory');
        $names = array_replace(array_flip($sorted_dirs), array_flip($tree_dirs));
        if (!empty($names)) {
            $sorted_dirs = array_keys($names);

            $arr = array();
            foreach($sorted_dirs as $name) {
                foreach($dirTree as $index => $item) {
                    if (!empty($item['directory']) && $item['directory'] == $name) {
                        array_push($arr, $item);
                        break;
                    }
                }
            }
            $dirTree = $arr;
        }

        return compact('menus', 'dirTree');
    }

    //get basename of realpath, support chinese
    protected function basename($realpath) {
        $realpath = preg_replace('/\/$/', '', $realpath);
        $arr = explode('/', $realpath);
        if (count($arr) < 2) {return $realpath;}

        return array_pop($arr);
    }

    //get cache key
    protected function getCacheKey($cateId, $dataType = 'tree', $maxScanDeep = 0) {
        $prefix = FSC::$app['config']['theme'];
        return "{$prefix}_{$dataType}_{$maxScanDeep}_{$cateId}";
    }

    //根据目录的绝对路径,获取网站的相对路径
    protected function getCurrentWebroot($dir_realpath) {
        if (empty($dir_realpath)) {return '/';}

        $webroot = FSC::$app['config']['content_directory'];
        $arr = explode($webroot, $dir_realpath);
        if (count($arr) < 2) {
            return $webroot;
        }

        return "{$webroot}{$arr[1]}/";
    }

}