<?php
class view{
	private $vars = array();
	private $head_arr = array();

	public function __construct() {
		$_ENV['_theme'] = 'default';
		$_ENV['_view_diy'] = FALSE;
	}

	public function assign($k, &$v) {
		$this->vars[$k] = &$v;
	}

	public function assign_value($k, $v) {
		$this->vars[$k] = $v;
	}
	public function display($filename = null) {
		$_ENV['_tplname'] = is_null($filename) ? $_GET['control'].'_'.$_GET['action'].'.htm' : $filename;
		extract($this->vars, EXTR_SKIP);
		include $this->get_tplfile($_ENV['_tplname']);
	}
	private function get_tplfile($filename) {
		if(APP_NAME == 'nzcms_member'){ //如果是会员中心，只有一个默认default风格
			$_ENV['_theme'] = 'default';
		}
		$view_dir = APP_NAME.($_ENV['_view_diy'] ? '_view_diy' : '_view').'/';
		$php_file = RUNTIME_PATH.$view_dir.$_ENV['_theme'].','.$filename.'.php';

		if(!is_file($php_file) || DEVMODE) {
			$tpl_file = core::get_original_file($filename, VIEW_PATH.$_ENV['_theme'].'/');
			if(!$tpl_file) {
				throw new Exception('模板文件 '.$_ENV['_theme'].'/'.$filename.' 不存在');
			}
			if(FW($php_file, $this->tpl_parse($tpl_file)) === false) {
				throw new Exception("写入模板编译文件 $filename 失败");
			}
		}
		return $php_file;
	}
	private function tpl_parse($tpl_file) {
		$reg_arr = '[a-zA-Z_]\w*(?:\[\w+\]|\[\'\w+\'\]|\[\"\w+\"\]|\[\$[a-zA-Z_]\w*\])*';
		$s = file_get_contents($tpl_file);
		$s = preg_replace_callback('#\{inc\:home\:([\w\.]+)\}#', array($this, 'parse_home_inc'), $s);
		$s = preg_replace_callback('#\{inc\:([\w\.]+)\}#', array($this, 'parse_inc'), $s);
		$s = preg_replace('#(?:\<\?.*?\?\>|\<\?.*)#s', '', $s);
		$s = preg_replace('#\{php\}(.*?)\{\/php\}#s', '<?php \\1 ?>', $s);
		$s = preg_replace_callback('#\{block\:([a-zA-Z_]\w*)\040?([^\n\}]*?)\}(.*?){\/block}#s', array($this, 'parse_block'), $s);
		while(preg_match('#\{loop\:\$'.$reg_arr.'(?:\040\$[a-zA-Z_]\w*){1,2}\}.*?\{\/loop\}#s', $s))
			$s = preg_replace_callback('#\{loop\:(\$'.$reg_arr.'(?:\040\$[a-zA-Z_]\w*){1,2})\}(.*?)\{\/loop\}#s', array($this, 'parse_loop'), $s);
		while(preg_match('#\{if\:[^\n\}]+\}.*?\{\/if\}#s', $s))
			$s = preg_replace_callback('#\{if\:([^\n\}]+)\}(.*?)\{\/if\}#s', array($this, 'parse_if'), $s);
		$s = preg_replace('#\{\@([^\}]+)\}#', '<?php echo(\\1); ?>', $s);
		$s = preg_replace_callback('#\{(\$'.$reg_arr.')\}#', array($this, 'parse_vars'), $s);
		$head_str = empty($this->head_arr) ? '' : implode("\r\n", $this->head_arr);
		$s = "<?php defined('APP_NAME') || exit('Access Denied'); $head_str\r\n?>$s";
		$s = str_replace('?><?php ', '', $s);
		return $s;
	}
	private function parse_inc($matches) {
		if(APP_NAME == 'nzcms_member'){ //如果是会员中心，只有一个默认default风格
			$_ENV['_theme'] = 'default';
		}
		$filename = 'inc-'.$matches[1];
		$tpl_file = core::get_original_file($filename, VIEW_PATH.$_ENV['_theme'].'/');

		if(!$tpl_file) {
			throw new Exception('模板文件 '.$_ENV['_theme'].'/'.$filename.' 不存在');
		}
		return file_get_contents($tpl_file);
	}
	private function parse_home_inc($matches) { //只存在于会员中心模板
		$_ENV['_theme'] = $_ENV['_hometheme'];

		$filename = 'inc-'.$matches[1];
		$tpl_file = core::get_original_file($filename, APP_PATH.'view/'.$_ENV['_theme'].'/');

		if(!$tpl_file) {
			throw new Exception('模板文件 '.$_ENV['_theme'].'/'.$filename.' 不存在');
		}
		return file_get_contents($tpl_file);
	}
	private function parse_block($matches) {
		$func = $matches[1];
		$config = $matches[2];
		$s = $matches[3];

		$lib_file = core::get_original_file('kp_block_'.$func.'.lib.php', BLOCK_PATH);
		if(!is_file($lib_file)) return '';
		$lib_str = file_get_contents($lib_file);
		if(!DEVMODE) $lib_str = _strip_whitespace($lib_str);
		$lib_str = core::clear_code($lib_str);
		$this->head_arr['kp_block_'.$func] = $lib_str;

		$s = $this->rep_double($s);
		$config = $this->rep_double($config);
		$config_arr = array();
		preg_match_all('#([a-zA-Z_]\w*)="(.*?)" #', $config.' ', $m);
		foreach($m[2] as $k=>$v) {
			if(isset($v)) $config_arr[strtolower($m[1][$k])] = addslashes($v);
		}
		unset($m);
		$func_str = 'kp_block_'.$func.'('.var_export($config_arr, 1).');';
		$before = $after = '';
		if(substr($func, 0, 7) == 'global_') {
			$this->head_arr[$func] = '$gdata = '.$func_str;
		}else{
			$before .= '<?php $data = '.$func_str.' ?>';
			$after .= '<?php unset($data); ?>';
		}
		if($_ENV['_view_diy']) {
			$this->kp_block_id++;
			$before .= '<span kp_block_diy="before" kp_block_id="'.$this->kp_block_id.'"></span>';
			$after .= '<span kp_block_diy="after" kp_block_id="'.$this->kp_block_id.'"></span>';
		}
		return $before.$s.$after;
	}
	private function parse_loop($matches) {
		$args = explode(' ', $this->rep_double($matches[1]));
		$s = $this->rep_double($matches[2]);

		$arr = $this->rep_vars($args[0]);
		$v = empty($args[1]) ? '$v' : $args[1];
		$k = empty($args[2]) ? '' : $args[2].'=>';
		return "<?php if(isset($arr) && is_array($arr)) { foreach($arr as $k&$v) { ?>$s<?php }} ?>";
	}
	private function parse_if($matches) {
		$expr = $this->rep_double($matches[1]);
		$expr = $this->rep_vars($expr);
		$s = preg_replace_callback('#\{elseif\:([^\n\}]+)\}#', array($this, 'rep_elseif'), $this->rep_double($matches[2]));
		$s = str_replace('{else}', '<?php }else{ ?>', $s);
		return "<?php if ($expr) { ?>$s<?php } ?>";
	}
	private function rep_elseif($matches) {
		$expr = $this->rep_double($matches[1]);
		$expr = $this->rep_vars($expr);
		return "<?php }elseif($expr) { ?>";
	}
	private function parse_vars($matches) {
		$vars = $this->rep_double($matches[1]);
		$vars = $this->rep_vars($vars);
		return "<?php echo(isset($vars) ? $vars : ''); ?>";
	}
	private function rep_double($s) {
		return str_replace('\"', '"', $s);
	}
	private function rep_vars($s) {
		$s = preg_replace('#\[(\w+)\]#', "['\\1']", $s);
		$s = preg_replace('#\[\"(\w+)\"\]#', "['\\1']", $s);
		$s = preg_replace('#\[\'(\d+)\'\]#', '[\\1]', $s);
		return $s;
	}
}
