<?php
/*
	DevSaver Web Framework
	Copyright (c) 2013-2016 DevSaver. 
	All rights reserved.
		web:  www.devsaver.com
		mail: support@devsaver.com		
*/

// dependencies

/**
* description
*
* @library	
* @author	
* @since	
*/
class CSkinEditor extends CPlugin{
	
	var $tplvars; 

	function __construct() {
		//$this->CPlugin($db, $tables , $templates);
		$this->name = "skineditor";
	}

	function DoEvents(){
		global $base, $_CONF, $_TSM , $_VARS , $_USER , $_BASE , $_SESS;

		if ($_GET["mod"] == $this->name) {
			$this->tpl_module = $this->module->plugins["modules"]->LoadDefaultModule($this->name);
			parent::DoEvents();

			$sub = $_GET["sub"];
			$action = $_GET["action"];

			//read the module
			switch ($sub) {
				case "landing":
					$sub = "skins";
				case "skins":
				case "fonts":
					$_SESS["skineditor"] = "";

					//$this->plugins["seo"]->AppendToHead('<script src="3rdparty/codemirror/addon/emmet/emmet.js"></script>');
				
					$data = new CSQLAdmin($sub, $this->__parent_templates,$this->db,$this->tables,$extra);
					$data->setAclMod($this->tpl_module);
					$this->PrepareFields($data->forms["forms"]);
					$this->PrepareSkinFields($data->forms["forms"]);
					
					$data->functions = array( 
							"onstore" => array(&$this , "StoreRecord"),
//							"ondelete" => array(&$this , "DeleteRecord"),
					);					

					if ($sub == "skins") {
						$data->functions["list_process"] = array(&$this , "ProcessSkins");
					}
					

					return $data->DoEvents();
				break;

				case "duplicate":
					return $this->Duplicate();
				break;

				case "settings":
						$data = new CFormSettings($this->forms_path  . $sub . ".xml" ,$_CONF["forms"]["admintemplate"] , $this->db,$this->tables);
						$this->PrepareDashboard($data->form);
						$this->PrepareFields($data->form);

						if ($data->Done()) {
							

							$skin = $this->db->QFetchArray("SELECT * FROM {$this->tables['core:skins']} WHERE skin_id=%d" , array($_POST['set_skin']));
							$fields = CForm::KeyFields($data->form);

							if (is_array($fields)) {
								foreach ($fields as $key => $val) {
									$vars[$val] = $_POST[$val];
								}								
							}
								
							$this->vars->SetVars(
								$vars
							);
						}
						
						return $data->Show(							
							$this->vars->GetVars(
								CForm::KeyFields($data->form)
							)
						
						);
				break;

				case "add-skin":
					$data = new CFormSettings($this->forms_path  . $sub . ".xml" ,$_CONF["forms"]["admintemplate"] , $this->db,$this->tables);
					$this->PrepareDashboard($data->form);
					$this->PrepareAddSkinFields($data->form);

					if ($data->Done()) {
						$this->CreateNewSkin();
					}
					
					return $data->Show();
				break;


				case "preview":
					return $this->Preview();
				break;
			}
		}
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function DeleteRecord($record) {
		if (isModSub("skineditor" , "skins") && $record["skin_id"]) {
			CFile::Remove("../upload/skins/{$record[skin_id]}.css");
		}

		if (isModSub("skineditor" , "fonts") && $record["skin_id"]) {
			CFile::Remove("../upload/skins/lang_{$record[skin_id]}.css");
		}

	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function StoreRecord($record) {

		if (isModSub("skineditor" , "skins") && $record["skin_id"]) {


			$minifier = new MatthiasMullie\Minify\CSS();
			$minifier->add($record["skin_css"]);
			$record["skin_css"] = $minifier->minify();			

			CFile::Save("../upload/skins/{$record[skin_id]}.css" , $record["skin_css"]);
		}

		if (isModSub("skineditor" , "fonts") && $record["skin_id"]) {


			$minifier = new MatthiasMullie\Minify\CSS();
			$minifier->add($record["skin_css"]);
			$record["skin_css"] = $minifier->minify();
			
			CFile::Save("../upload/skins/lang_{$record[skin_id]}.css" , $record["skin_css"]);
		}
		
	}

	
	

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function Duplicate() {

		$item = $this->db->QFetchArray("SELECT * FROM {$this->tables['core:skins']} WHERE skin_id={$_GET['skin_id']}");

		if (!is_array($item)) {
			return "Invalid link !";
		}

		unset($item["skin_id"]);
		unset($item["skin_modules"]);
		unset($item["skin_default"]);
		unset($item["skin_system"]);
		unset($item["skin_modules_global"]);

		$item["skin_name"] .= " (Copy)";

		$sid = $this->db->QueryInsert(
			$this->tables['core:skins'] , 
			$item
		);

		
		//redirect to details page
		urlredirect(
			"index.php?mod=skineditor&sub=skins&skin_id={$sid}&action=edit&returnurl=" . 
				urlencode("index.php?mod=skineditor&sub=skins")
		);
				
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function Preview() {
		global $_CONF , $_SESS;

		$_SESS["skineditor"] = $_POST["skin_id"];

		CFile::Save("../upload/skins/preview.css" , $_POST["skin_css"]);

		echo $_CONF["url"];
		die();
	}

		/*
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function PrepareSkinFields(&$forms) {

		if (isModSubAct("skineditor" , "fonts" , "add")) {

			//debug($this->CSSReadFiles("../assets/css/"),1);

			$forms["add"]["fields"]["box"][2]["fields"]["skin_css"]["default"] = $this->CSSReadFiles("../assets/css/");
		}
		
	}
	


	function CSSBuilsClasses($res) {
		foreach ($res as $key => $val) {

			$data[] .= implode(",\n" , $val) . " {\n\t" . str_replace(";" , "; \n\t" , $key) .  "\n}\n" ;
		}
		
		return implode("\n" , $data);
	}
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CSSProcess($css , &$results) {

		$css = preg_replace('!/\*.*?\*/!s', '', $css);
		$css = preg_replace('/\n\s*\n/', "\n", $css);
		
		$lines = explode("\n" , $css);


		foreach ($lines as $key => $val) {

			if (stristr($val , "font-family")) {


				//read to the top until you find the start of the class
				$tmpk = $key;

				while ( !stristr($lines[$tmpk] , "{")) {
					$tmpk --;
				}

				//go down till in find the font weight;
				$tmpk2 = $tmpk;
				$weight = "";

				while ( !stristr($lines[$tmpk2] , "}") ) {

					if (stristr($lines[$tmpk2], "font-weight")) {
						$weight = trim($lines[$tmpk2]);
					}
					
					$lines[$tmpk];
					$tmpk2 ++;
				}




				//go back till i find } or first key
				
				while ( !stristr($lines[$tmpk] , "}") && ($tmpk >= 0)) {

					$results[trim($val) . $weight][] = $lines[$tmpk];
					$tmpk --;
				}
			}			
		}		

		//debug($results);
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CSSProcessFinallClasses($res) {

		foreach ($res as $key => $val) {

			if ($this->CSSCleanpCheckKey($key)) {
				unset($res[$key]);
			} else {						
				foreach ($val as $k => $v) {
					if (trim($v)) {
						$res[$key][$k] = $this->CSSCleanup($v);
					} else {
						unset($res[$key][$k]);
					}
				}

				sort($res[$key]);
			}
			
		}
		
		return $res;
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CSSCleanpCheckKey($data) {

		$excempt = array(
			"Glyphicons",
			"inherit",
			"icomoon",
			"Fontawesome"
		);

		foreach ($excempt as $key => $val) {

			if (stristr($data , $val)) {
				return true;
			}
		}
		
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CSSCleanup($data) {

		$data = str_replace("{" , "" , $data);
		$data = trim($data);

		if (substr($data, -1) == ",") {
			$data = substr($data, 0, -1);
		}		

		return trim($data);
	}
	
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CSSReadFiles($path = "assets/css/") {

		$files = CDir::GetFiles($path , ".css");

		$res = array();	

		$excempt = array(
			"/admin.editor.",
			"/font." , 
			"/plugin.",
			"layout.bootstrap",
		);

		//$files= array("../assets/css//global.tabs.css");

		foreach ($files as $key => $val) {

			foreach ($excempt as $k => $v) {

				if (stristr($val , $v ) ) {
					unset($files[$key]);
				}
			}
		}
			
		foreach ($files as $key => $val) {

			$tmp = Cfile::Get($val);

			if (stristr($tmp , "font-family")) {
				$data = $this->CSSProcess($tmp , $res);
			}
		}

		//debug($res,1);
		$res = $this->CSSProcessFinallClasses($res);

		return "/*put the font @import on the first line, then replace the old families with the one one. */ \n\n" . $this->CSSBuilsClasses($res);
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CreateNewSkin() {
		global $_CONF;

		$skin = array(
			"skin_name"		=> $_POST["title"],
			"skin_status"	=> "1",
			"skin_css"		=> "",
			"skin_device"	=> "1,2,3"
		);

		switch ($_POST["type"]) {

			//empty skin
			case "1":

			break;

			//based on skin
			case "2":

				if ($_POST["skin"]) {
					$skin["skin_css"] = $token = CHTTP::NewInstance()
						->Get($_CONF["url"] . 'upload/skins/' . $_POST["skin"] . ".css")
						->Raw(); 
				} else {
					$skin["skin_css"] = $token = CHTTP::NewInstance()
						->Get($_CONF["url"] . 'assets/css/skin.php?admin=true')
						->Raw(); 
				}
			break;

			case "3":

				$content = 	$token = CHTTP::NewInstance()
					->Get($_CONF["url"] . 'assets/css/skin.php?admin=true')
					->Raw(); 

				$colors = new CConfig("../assets/css/skin.xml");

				if (is_array($colors->vars["skin"])) {
					foreach ($colors->vars["skin"] as $key => $val) {
						
						if ($val["type"] == "colorpicker") {
							$old[]	= $val["default"];
							$old[]	= $this->hex2rgb($val["default"]);
							$new[]	= $_POST[$key];
							$new[]	= $this->hex2rgb($_POST[$key]);
						}
					}

					$content = str_replace(
						$old , 
						$new , 
						$content
					);
				}

				$skin["skin_css"] = $content;
			break;

			case "4":
				$skin["skin_parent"] = $_POST["parent"];
			break;

		}
		
	
		$id = $this->db->QueryInsert(
			$this->tables['core:skins'],
			$skin
		);

		urlredirect("index.php?mod=skineditor&sub=skins&action=edit&skin_id={$id}&returnurl=" . urlencode("index.php?mod=skineditor&sub=skins"));
	}
	

	function hex2rgb($hex ) {
	   $hex = str_replace("#", "", $hex);

	   if(strlen($hex) == 3) {
		  $r = hexdec(substr($hex,0,1).substr($hex,0,1));
		  $g = hexdec(substr($hex,1,1).substr($hex,1,1));
		  $b = hexdec(substr($hex,2,1).substr($hex,2,1));
	   } else {
		  $r = hexdec(substr($hex,0,2));
		  $g = hexdec(substr($hex,2,2));
		  $b = hexdec(substr($hex,4,2));
	   }
	   $rgb = array("r"	=> $r, "g"	=> $g, "b"	=> $b);
	   //return implode(",", $rgb); // returns the rgb values separated by commas

	   return $r . "," . $g . "," . $b ;//$rgb; // returns an array with the rgb values
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @accessokay wi
	*/
	function PrepareAddSkinFields(&$form) {
		//debug($form,1);

		$colors = new CConfig("../assets/css/skin.xml");

		if (is_array($colors->vars["skin"])) {
			foreach ($colors->vars["skin"] as $key => $val) {
				if ($val["type"] == "colorpicker") {
					$val["required"] = "true";
					$val["validate"] = "A:1:200";
				}

				$form["fields"]["box"]["0"]["fields"][$key] = $val;				
			}			
		}
		
	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ProcessSkins($items , $count) {

		if (is_array($items)) {
			foreach ($items as $key => $val) {
				if (!$val["skin_parent"]) {
					$_skins[$val["skin_id"]] = $val;
				}				
			}

			foreach ($items as $key => $val) {
				if ($val["skin_parent"]) {
					$_skins[$val["skin_parent"]]["sub"][] = $val;
				}				
			}
		
			ksort($_skins);

			$skins = array();

			foreach ($_skins as $key => $val) {
				$skins[] = $val;

				if ($val["sub"]) {
					$cnt = 1;
					foreach ($val["sub"] as $k => $v) {
						$pref = "<nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
						$v["skin_name"] = $pref . $v["skin_name"] . "</nobr>";


						$skins[] = $v;
					}
					
				}
				
			}
			
			
		}
		


		return array(
			"items"	=> $skins,
			"count"	=> $count
		);

	}
	
}

?>