<?php
/**

0.16 
	소스코드 약간 정리. writeHttpHeader(0.15에서추가됨)
	확장자 강제 가능 (.pug, .htm등)

0.15
	action_file 함수 추가 -> 파일이 있을경우, pug파일 자동로딩 처리
	set_options -> layout 에 파라메터를 넘길때 사용
0.14	
	view_dir -> 상대경로로
	view 존재하지 않을때 처리 변경		

0.13 
	action callback 에 app context 추가 
	ex) $app->action(function(&view, $app){});

0.12 
	route parsing 강화, routeinfo, contentno 지원 /api/method/DIGITS 일때 
	route : api/method 
	contentno : DIGITS
0.11 
	cli지원, cli모드에서 http 헤더 안보냄

0.1
	새로운 routing 모델 도입
	pug 융합
	
*/
//namespace Pug;

error_reporting(E_ALL&~E_NOTICE&~E_DEPRECATED);
ini_set('display_errors', 1);

class Application
{
    //protected $route;
    public $route;
	public $routeinfo;
	public $view_dir = 'view/';
	public $found = false;
	public $layout = 'layout';
	
    public function __construct($srcPath, $pathInfo)
    {
        $this->route = ltrim($pathInfo, '/');

		$this->routeinfo = $this->parseRoute($this->route);
		//error_log("routeinfo: ".json_encode($this->routeinfo));

        spl_autoload_register(function ($class) use ($srcPath) {
            if (
                strstr($class, 'Pug') /* new name */ ||
                strstr($class, 'Jade') /* old name */
            ) {
                include($srcPath . str_replace("\\", DIRECTORY_SEPARATOR, $class) . '.php');
            }
        });
    }
	
	public function __destruct() {
		if (!$this->found) {
			if (php_sapi_name() != 'cli') 
				header("HTTP/1.0 404 Not Found");
			die("[$this->route] is not found.");
		}
	}	
	
	function parseRoute($route)
	{
		//echo "$route\n";
		//commandline 인자분리
		if (php_sapi_name() == 'cli' && preg_match('/\?(.+)/', $route, $matches)==1) {
			//print_r($matches);
			parse_str($matches[1], $_REQUEST);
			//print_r($_REQUEST);
			//http_parse_params(
			//die();
		}		


		if (preg_match('/(.+)(\/(\d+$|\d+\/\?|\d+\?))/', $route, $matches) == 1) {
			//print_r($matches);
			$route = $matches[1];
			preg_match('/\d+/', $matches[3], $content);
			$contentno = $content[0];
			//print_r($matches);
			//print_r($content);die();
		} else 
		if(preg_match('/(.+\/*)\?/', $route, $matches) == 1){
			//print_r($matches);
			$route = $matches[1];
		}
		
		if ($route == '')
			$route = 'index';
		
		$result = array(
				route =>$route,
				contentno=>$contentno
		);
		return $result;
	}
	
	function _render_pug($fn, $args=null)
	{
	    $pug    = new Pug\Pug(array(prettyprint=>'true'));
     	$output = $pug->render($fn, $args);
		if ($this->layout) {
			//$layoutfn = getcwd() . '/'.$this->view_dir.'/'. $this->layout . $pug->getExtension();
			$layoutfn = $this->view_dir.'/'. $this->layout . $pug->getExtension();
			if (is_file($layoutfn)) {
				//echo file_get_contents($layoutfn);
				$params = $this->layout_params?:array();
				//if (!$params)
					//$params = array();
				$params[body] = $output;
				//print_r($params);
				$output = $pug->render($layoutfn, $params);//array(body=>$output));
			} else {
				throw new \Exception("layout file not found.($layoutfn)");
			}
		}
		return $output;
	}

    public function action($path, \Closure $callback)
    {
		//echo "ROUTE: $this->route PATH: $path\n";
		//$fn = getcwd().'/'.$this->view_dir.'/'.$this->route;
		$fn = $this->view_dir.'/'.$this->route;
		// echo $fn."\n";
		if (is_file($fn)) { // 파일이 존재하는경우 그냥 output
			$this->found = true;
			$this->writeHttpHeader($fn);
			readfile($fn);			
			die();
		}
		if ($path == '/')
			$path = '/index';
		//if (strpos($route, ltrim($path, '/')) === 0) {
		if ($this->routeinfo[route] == ltrim($path, '/')) {
			$this->found = true;
			
            //$pug    = new Pug\Pug(array(prettyprint=>'true'));
            $vars   = $callback($view, $this) ?: array();
			if (!$view)
				return;			
			//$fn = $this->view_dir.'/'. $view . $pug->getExtension();
			$fn = $this->view_dir.'/'. $view;
			if (!pathinfo($fn, PATHINFO_EXTENSION))
				$fn .= '.pug';
			if (!file_exists($fn))
				throw new Exception("file $fn not exists\nviewdir: $this->view_dir\npath: $view");
			try {
				$output = $this->_render_pug($fn, $vars);
				$this->writeHttpHeader();
				echo $output;				
				die();
			} catch(Exception $e) {
				//echo eval($fn);
				throw $e;
			}
        }
    }
	
	public function action_file(\Closure $callback) {
		$fn = $this->view_dir.$this->route.'.pug';
		if (file_exists($fn)) {
			$args = $callback($this->route, $cancel);
			if ($cancel)
				return;
			$this->found = true;
			$html = $this->_render_pug($fn, $args);
			echo $html;
			die();
		}
	}
	public function set_options(\Closure $callback) {
		$o = $callback();
		if (isset($o[view_dir]))
			$this->view_dir = $o[view_dir];
		if (isset($o[layout]))
			$this->layout = $o[layout];
		//echo "xxx".is_array($o[layout_params]);
		//print_r($o[layout_params]);
		if (is_array($o[layout_params])) {
			$this->layout_params = $o[layout_params];
		}
	}
	function writeHttpHeader($fn=null)
	{
		if (php_sapi_name() == 'cli')  // command라인에서는 안한다
			return;
		if ($fn) {
			$fn = strtolower($fn);
			$i = pathinfo($fn);
			switch($i[extension]) {
			case 'css':
				header('Content-Type: text/css');
				break;
			case 'js':
				header('Content-Type: application/javascript');
				break;
			default:
				header('Content-Type: '.mime_content_type ($fn));
			}
			return;
		}			
		header('Access-Control-Allow-Origin: *');
		header('Content-Type: text/html; charset=utf-8');
//		}
//		header('Content-Type: text/html; charset=utf-8');						
	}
}

$app = new Application(__DIR__ . '/../pug/', isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : (isset($argv, $argv[1]) ? $argv[1] : ''));

function __add_include_path($path)
{
	//$path = '/usr/lib/pear';
	set_include_path(get_include_path() . PATH_SEPARATOR . $path);
}
__add_include_path('../');
__add_include_path('../fly2');

require 'utils.php';
/*
if (php_sapi_name() != 'cli') {
	header('Access-Control-Allow-Origin: *');
	header('Content-Type: text/html; charset=utf-8');
	// 기본으로 무조건 열면 문제가 생긴다. 파일아웃풋때 헤더 에러 등등
}
*/
?>