<?php
/**
 * @package Unlimited Elements
 * @author UniteCMS.net
 * @copyright (C) 2017 Unite CMS, All Rights Reserved. 
 * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 * */
defined('UNLIMITED_ELEMENTS_INC') or die('Restricted access');


class UniteCreatorExporter extends UniteCreatorExporterBase{
	
	const MULTIPLE_FOLDERS_FILENAME = "multiple";
	const MUST_TYPE_FORCE_REGULAR = "force_regular_addon";
	
	private $addon;
	
	protected $objAddons;
	protected $pathExportAddons;
	protected $filepathAddonZip;
	protected $pathExportAddon;
	protected $pathExportAddonAssets;

	//export categories
	
	protected $pathExportCategories;
	protected $pathExportCategory;
	protected $pathExportCategoryAddons;
	
	protected $filepathCategoryZip;
	protected $filenameCategoryZip;
	
	
	//import	
	private $isPathSingle = false;
	
	private $pathImportAddon;
	private $pathImportAddonAssets;
	private $isImportedOnce = false;
	private $textLogShort = "";
	private $importedAddonType = "";
	private $mustAddonType = null;
	private $downloadFilenameEnding = null;
	private $catExportData = null;
	private $lastImportedAddonID;
	private $lastImportedCatID;
	private static $arrImportedAddons = array();
	
	/**
	 * constructor
	 */
	public function __construct(){
		parent::__construct();
		
		$this->objAddons = new UniteCreatorAddons();
	}
	
	
	/**
	 * validate that the addon exists
	 */
	private function validateInited(){
		if(empty($this->addon))
			UniteFunctionsUC::throwError("export error: addon not inited");
	}
	
	
	/**
	 * print all globals variables
	 */
	private function printVars(){
		
		$vars = get_object_vars($this);
		
		dmp($vars);
	}
		
	
	/**
	 * init by addon
	 * @param $addon
	 */
	public function initByAddon(UniteCreatorAddon $addon){
		
		$this->addon = $addon;
		
	}
	
	
	
	private function a_________EXPORT_ADDON_______(){}
	
	
	
	/**
	 * create export folder if not exists
	 */
	private function prepareExportFolders_addons(){
	
		$this->prepareExportFolders_globalExport();
		
		$this->pathExportAddons = $this->pathExport."addons/";
		UniteFunctionsUC::mkdirValidate($this->pathExportAddons, "Export Addons");
		
		//clear folder
		UniteFunctionsUC::deleteDir($this->pathExportAddons, false);
		
		$this->pathExportAddon = $this->pathExportAddons."addon_".UniteFunctionsUC::getRandomString(10)."/";
		$this->pathExportAddonAssets = $this->pathExportAddon."assets/";
		
		//create index.html
		UniteFunctionsUC::writeFile("", $this->pathExportAddons."index.html");

		UniteFunctionsUC::mkdirValidate($this->pathExportAddon, "Export Addon");
		
		$addonName = $this->addon->getName();
		
		$tempFilenameZip = $addonName."_".UniteFunctionsUC::getRandomString(10).".zip";
		
		$this->filepathAddonZip = $this->pathExportAddons.$tempFilenameZip;
		
	}
	
		
	
	/**
	 * modify includes in config that it will be saved in new way
	 */
	private function modifyConfig($config){
		
		$includes = UniteFunctionsUC::getVal($config, "includes");
		
		$arrJs = UniteFunctionsUC::getVal($includes, "js");
		$arrCss = UniteFunctionsUC::getVal($includes, "css");
		
		$arrJs = HelperUC::arrUrlsToRelative($arrJs, true);
		$arrCss = HelperUC::arrUrlsToRelative($arrCss, true);
		
		if(!empty($arrJs))
			$includes["js"] = $arrJs;
		
		if(!empty($arrCss))
			$includes["css"] = $arrCss;
		
		$config["includes"] = $includes;
		
		//no export dynamic post ID
		unset($config["options"]["dynamic_post"]);

		//modify params, exclude dynamic post
		$params = UniteFunctionsUC::getVal($config, "params");
		if(empty($params))
			$params = array();
			
		foreach($params as $key=>$param){
			
			$type = UniteFunctionsUC::getVal($param, "type");
			
			switch($type){
				
				case UniteCreatorDialogParam::PARAM_POSTS_LIST:
					
					//remove dynamic post example
					
					unset($config["params"][$key]["post_example"]);
					unset($config["params"][$key]["post_example_text"]);
					
				break;
			}
			
		}
		
		
		return($config);
	}
	
	
	
	/**
	 * get xml from addon
	 */
	private function getJsonFromAddon(){
		
		$arrAddon = array();
		
		$addonType = $this->addon->getType();
		
		$addonName = $this->addon->getName();
		$addonAlias = $this->addon->getAlias();
		
		$catTitle = $this->addon->getCatTitle();
		//set alias and name by type
		if(!empty($addonType) && empty($addonAlias)){
			$addonAlias = $addonName;
			$addonName = $addonName."_".$addonType;
		}
		
		if($this->mustAddonType == self::MUST_TYPE_FORCE_REGULAR){
			$addonType = "";
			if(!empty($addonAlias)){
				$addonName = $addonAlias;
				$addonAlias = "";				
			}
		}
		
		$arrAddon["addontype"] = $addonType;
		$arrAddon["cattitle"] = $catTitle;
		$arrAddon["name"] = $addonName;
		$arrAddon["alias"] = $addonAlias;
		
		$arrAddon["title"] = $this->addon->getTitle();
		$arrAddon["description"] = $this->addon->getDescription();
		
		$arrConfig = $this->addon->getConfig();
		$arrAddon["config"] = $this->modifyConfig($arrConfig);
		
		$arrTemplates = $this->addon->getTemplates();
		
		$arrTemplateNames = array();
		foreach($arrTemplates as $name=>$content){
			if(!empty($content))
				$arrTemplateNames[] = $name;
		}
		
		$arrAddon["templates"] = $arrTemplateNames;
		
		$arrAddon = UniteProviderFunctionsUC::applyFilters(UniteCreatorFilters::FILTER_EXPORT_ADDON_DATA, $arrAddon);
		
		$json = json_encode($arrAddon, JSON_PRETTY_PRINT);
		
		return($json);
	}
	
	
	/**
	 * get json category from addon, or from set cat data
	 */
	protected function getJsonCategoryFromAddon(){
		
		//get from global saved data (fro category addons)
		if(!empty($this->catExportData)){
			$jsonData = json_encode($this->catExportData);
			return($jsonData);
		}
		
		
		//get from addon data
		$catID = $this->addon->getCatID();
		$addonType = $this->addon->getType();
		
		$arrData = $this->getExportCatData($catID, $addonType);
		if(empty($arrData))
			return(null);
		
		$jsonData = json_encode($arrData);
		
		return($jsonData);
	}
	
	
	/**
	 * write file if not empty content
	 */
	private function writeFile($filename, $content){
		
		$filepath = $this->pathExportAddon.$filename;
		if(!empty($content))
			UniteFunctionsUC::writeFile($content, $filepath);
	}
	
	
	/**
	 * write export data
	 */
	private function createExportFiles(){
		
		//write addon main file
		$strJson = $this->getJsonFromAddon();
		$this->writeFile("addon.json", $strJson);
		
		//write category json file
		$strJsonCat = $this->getJsonCategoryFromAddon();
		if(!empty($strJsonCat))
			$this->writeFile("category.json", $strJsonCat);
		
		//write template files
		$arrTemplates = $this->addon->getTemplates();		
		
		//write templates
		foreach($arrTemplates as $name=>$content){
			$filename = $name.".tpl";
			$this->writeFile($filename, $content);
		}
		
		//write default data
		$defaultData = $this->addon->getDefaultData();
		$defaultData = $this->addon->modifyAddonDataConvertToUrlAssets($defaultData);
		
		if(!empty($defaultData)){
			$defaultData = json_encode($defaultData, JSON_PRETTY_PRINT);
			$this->writeFile("default_data.json", $defaultData);
		}
		
	}
	
	
	/**
	 * check if assets path is ready for export
	 */
	private function isPathAssetsReadyForExport($pathAssets){
		
		$objAddonType = $this->addon->getObjAddonType();
				
		$isUnderAssets = HelperUC::isPathUnderAssetsPath($pathAssets, $objAddonType);
				
		if(!$isUnderAssets)
			return(false);
		
		if(is_dir($pathAssets) == false)
			return(false);
		
		$isPathAssets = HelperUC::isPathAssets($pathAssets, $objAddonType);
		if($isPathAssets == true)
			return(false);
		
		return(true);
	}
	
	
	/**
	 * copy addon assets
	 */
	private function copyAssets(){
		
		
		$options = $this->addon->getOptions();
		$dirAssets = $this->addon->getOption("path_assets");
		
		
		if(empty($dirAssets))
			return(false);
		
		$pathAssets = $this->addon->getPathAssetsFull();
				
		$isReady = $this->isPathAssetsReadyForExport($pathAssets);
				
		if($isReady == false)
			return(false);
		
		//make assets folder
		UniteFunctionsUC::mkdirValidate($this->pathExportAddonAssets, "assets folder");
		
		$pathAssetsDest = $this->pathExportAddonAssets.$dirAssets."/";
		
		UniteFunctionsUC::mkdirValidate($pathAssetsDest, "assets dest folder: $dirAssets");
		
		UniteFunctionsUC::copyDir($pathAssets, $pathAssetsDest);
		
		//delete thumbs folders
		
		$arrDirs = UniteFunctionsUC::getDirList($pathAssets);
		
		foreach($arrDirs as $dir){
			
			switch($dir){
				case GlobalsUC::DIR_THUMBS_ELFINDER:
				case ".quarantine":
				case GlobalsUC::DIR_THUMBS:
					
					$pathDirDelete = $pathAssetsDest.$dir."/";
					
					UniteFunctionsUC::deleteDir($pathDirDelete);
					
				break;
			}
		}
						
	}
	
	
	/**
	 * make export zip file
	 */
	private function makeExportZipFile(){
		
		$zip = new UniteZipUC();
		$zip->makeZip($this->pathExportAddon, $this->filepathAddonZip);
		
				
		if(file_exists($this->filepathAddonZip) == false)
			UniteFunctionsUC::throwError("zip file {$this->filepathAddonZip} could not be created");
	}

	/**
	 * delete export addon folder
	 */
	private function deleteExportAddonFolder(){
		
		if(!empty($this->pathExportAddon) && is_dir($this->pathExportAddon))
			UniteFunctionsUC::deleteDir($this->pathExportAddon);
		
	}
	
	
	
	/**
	 * create category folder
	 */
	private function moveExportZipToFolder_createCategoryFolder($moveFolder){
		
		$addonType = $this->addon->getType();
		$catTitle = $this->addon->getCatTitle();
		
		$isSpecialType = HelperUC::isSpecialAddonType($addonType);
		if($isSpecialType == true)
			$catTitle = $addonType."_".$catTitle;
		
		if(empty($catTitle))
			return($moveFolder);
		
		$moveFolder = $moveFolder.$catTitle."/";
		
		if(is_dir($moveFolder))
			return($moveFolder);
		
		//create the folder
		UniteFunctionsUC::mkdirValidate($moveFolder, $catTitle);
			
		//write category file
		$addonType = $this->addon->getType();
		$catID = $this->addon->getCatID();
		$exportCatData = $this->getExportCatData($catID, $addonType);
		$this->createCategoryDataFile($exportCatData, $moveFolder);
		
		
		return($moveFolder);
	}
	
	
	/**
	 * write to folder
	 */
	private function moveExportZipToFolder($moveFolder, $createCategoryFolder = false){
		
		UniteFunctionsUC::validateDir($moveFolder);
		
		/**
		 * create category folder if needed
		 */
		if($createCategoryFolder == true)
			$moveFolder = $this->moveExportZipToFolder_createCategoryFolder($moveFolder);
		
		$addonAlias = $this->addon->getAlias();
		
		$addonName = $this->addon->getName();
				
		if($this->mustAddonType == self::MUST_TYPE_FORCE_REGULAR)
			$filename = $addonAlias.".zip";
		else
			$filename = $addonName.".zip";
		
		$newFilepath = $moveFolder.$filename;
		
		$success = rename($this->filepathAddonZip, $newFilepath);
		
		if($success == false)
			UniteFunctionsUC::throwError("Can't move export zip:$filename to the export folder");
		
	}
	
	
	/**
	 * download the zip file
	 */
	private function downloadFile(){
				
		$addonName = $this->addon->getName();
		$filename = $addonName;
		
		if(!empty($this->downloadFilenameEnding))
			$filename .= $this->downloadFilenameEnding;
		
		$filename .= ".zip";
				
		UniteFunctionsUC::downloadFile($this->filepathAddonZip, $filename);
	}
	
	
	/**
	 * set download filename ending
	 */
	public function setDownloadFilenameEnding($ending){
		$this->downloadFilenameEnding = $ending;
	}
	
	
	/**
	 * export addon - create export file and send it to download.
	 */
	public function export($moveFolder = null, $createCategoryFolders = false, $catExportData = null){
		
		$this->validateInited();
		
		try{
			$this->catExportData = $catExportData;
						
			$this->prepareExportFolders_addons();
			
			$this->createExportFiles();
			
			$this->copyAssets();
			
			$this->makeExportZipFile();
			$this->deleteExportAddonFolder();
			
			if(!empty($moveFolder)){
				$this->moveExportZipToFolder($moveFolder, $createCategoryFolders);
				$this->deleteExportAddonFolder();
			}
			else{
				
				$this->downloadFile();
				exit();
			}
			
		}catch(Exception $e){
			
			$this->deleteExportAddonFolder();
			throw $e;
		}
		
	}
	
	
	private function a_______EXPORT_CATEGORY______(){}
	
	
	
	/**
	 * prepare export categories folders
	 */
	private function prepareExportFolders_categories($catTitle, $exportType=""){
		
		$this->prepareExportFolders_globalExport();
		
		//delete cats folder only on first time create
		$clearCatsFolder = true;
		if(!empty($this->pathExportCategories))
			$clearCatsFolder = false;
		
		
		//make folders
		$this->pathExportCategories = $this->pathExport."categories/";
		UniteFunctionsUC::mkdirValidate($this->pathExportCategories, "Categories");
		
		
		//clear folder
		if($clearCatsFolder == true)
			UniteFunctionsUC::deleteDir($this->pathExportCategories, false);
		
		
		$this->pathExportCategory = $this->pathExportCategories."category_".UniteFunctionsUC::getRandomString(10)."/";
		
		UniteFunctionsUC::mkdirValidate($this->pathExportCategory, "Export Category");
		
		//create index.html
		UniteFunctionsUC::writeFile("", $this->pathExportCategories."index.html");
		
		//create actual category folder
		if(!empty($catTitle))
			$this->prepareExportFolders_category($catTitle, $exportType);
		
	}
	
	
	/**
	 * prepare category export folder and names
	 */
	private function prepareExportFolders_category($catTitle, $exportType=""){
		
		UniteFunctionsUC::validateNotEmpty($catTitle);
		
		UniteFunctionsUC::validateNotEmpty($this->pathExportCategory);
		
		$this->pathExportCategoryAddons = $this->pathExportCategory.$catTitle."/";
		UniteFunctionsUC::mkdirValidate($this->pathExportCategoryAddons, "$catTitle category");
		
		$this->prepareExportFolders_exportFilename($catTitle, $exportType);
	}
	
	
	/**
	 * prepare export folders file path and filename
	 */
	private function prepareExportFolders_exportFilename($catTitle, $exportType="", $addSuffix = true){
		
		$suffix = "";
		
		if($addSuffix == true){
			if(!empty($exportType))
				$suffix .= "_".$exportType;
			$suffix .= "_widgets";
		}
		
		$nameZip = $catTitle.$suffix;
		$nameZip = HelperUC::convertTitleToHandle($nameZip);
		
		$this->filenameCategoryZip = $nameZip.".zip";
		
		$tempFilenameZip = $nameZip."_".UniteFunctionsUC::getRandomString(10).".zip";
		
		$this->filepathCategoryZip = $this->pathExportCategories.$tempFilenameZip;
		
	}
	
	
	/**
	 * create category addons zips
	 * put them in the category export folder
	 */
	private function createCategoryAddonsZips($arrAddons, $catExportData = null){
		
		foreach($arrAddons as $addon){
			$objExport = new UniteCreatorExporter();
			$objExport->initByAddon($addon);
			
			$objExport->setMustImportAddonType($this->mustAddonType);
			
			$objExport->export($this->pathExportCategoryAddons, false, $catExportData);
		}
		
	}

	
	/**
	 * make export zip file
	 */
	private function makeExportCategoryZipFile(){
	
		$zip = new UniteZipUC();
		$zip->makeZip($this->pathExportCategory, $this->filepathCategoryZip);
		
		if(file_exists($this->filepathCategoryZip) == false)
			UniteFunctionsUC::throwError("zip file {$this->filepathCategoryZip} could not be created");
	}
	
	
	/**
	 * download the category zip file
	 */
	private function downloadCategoryFile(){
	
		UniteFunctionsUC::downloadFile($this->filepathCategoryZip, $this->filenameCategoryZip);
	}
	
	
	/**
	 * get addons array and cat title from catID
	 */
	private function exportCatAddons_getArrAddons($catID, $exportType){
		
		$objCat = new UniteCreatorCategories();
		$arrCat = $objCat->getCat($catID);
		
		if(empty($exportType))
			$exportType = UniteFunctionsUC::getVal($arrCat, "type");
		
		$catTitle = UniteFunctionsUC::getVal($arrCat, "title");
		$catType = UniteFunctionsUC::getVal($arrCat, "type");
		
		UniteFunctionsUC::validateNotEmpty($catTitle);
		
		$objAddons = new UniteCreatorAddons();
		
		$arrAddons = $objAddons->getCatAddons($catID, false, null, $exportType);
		
		if(empty($arrAddons))
			UniteFunctionsUC::throwError("No addons found in category: $catTitle (id - $catID)");
		
		//set addon types
		foreach($arrAddons as $addon){
			$addon->setType($exportType);
		}
				
		$output = array();
		$output["title"] = $catTitle;
		$output["type"] = $catType;
		$output["addons"] = $arrAddons;
		
		return($output);
	}
	
	
	/**
	 * export category data
	 */
	private function createCategoryDataFile($catExportData, $pathExport = null){
		
		$jsonData = json_encode($catExportData);
		
		if(empty($pathExport))
			$pathExport = $this->pathExportCategoryAddons;
		
		UniteFunctionsUC::validateDir($pathExport,"export category data");
		
		$filepathCategory = $pathExport."category.json";
		UniteFunctionsUC::writeFile($jsonData, $filepathCategory);
	}
	
	/**
	 * get category export data
	 */
	protected function getExportCatData($catID, $exportType){
		
		if(empty($catID))
			return(null);
		
		if(empty($exportType))
			$exportType = null;
		
		$objCat = new UniteCreatorCategory();
		$objCat->initByID($catID);
		$catExportData = $objCat->getExportCatData($exportType);
		
		return($catExportData);
	}
	
	
	/**
	 * export category addons
	 */
	public function exportCatAddons($catID, $exportType=null, $runFunc = null){
		
		$output = $this->exportCatAddons_getArrAddons($catID, $exportType);
		$arrAddons = $output["addons"];
		
		//get category data
		$catExportData = $this->getExportCatData($catID, $exportType);
		
		$catTitle = $catExportData["title"];
				
		try{
			
			$this->prepareExportFolders_categories($catTitle, $exportType);
			$this->createCategoryDataFile($catExportData);
			$this->createCategoryAddonsZips($arrAddons, $catExportData);
			
			if($runFunc === null){
				$this->makeExportCategoryZipFile();
				$this->downloadCategoryFile();	
				exit();
			}else{
				call_user_func(array($this, $runFunc));
			}
	
		}catch(Exception $e){
	
			throw $e;
		}
		
	}
	
	private function a_______EXPORT_CATS______(){}
	
	
	/**
	 * export multiple categories and their addons
	 */
	public function exportCatsAndAddons($arrCats, $exportType="", $runFunc = null, $filename = ""){
		
		UniteFunctionsUC::validateNotEmpty($arrCats);
		
		if(is_numeric($arrCats))
			$arrCats = array($arrCats);
			
		if(is_array($arrCats) == false)
			UniteFunctionsUC::throwError("export cats error: The categories should be array");
			
		try{
		
			//create general export folder
			$this->prepareExportFolders_categories("");
			
			foreach($arrCats as $catID){
				
				$output = $this->exportCatAddons_getArrAddons($catID, $exportType);
				
				$arrAddons = $output["addons"];
				$catTitle = $output["title"];
				$catAddonType = $output["type"];
				
				$catTitle = UniteProviderFunctionsUC::applyFilters(UniteCreatorFilters::FILTER_EXPORT_CAT_TITLE, $catTitle, $exportType, $catAddonType);
				
				$this->prepareExportFolders_category($catTitle, $exportType);
				$this->createCategoryAddonsZips($arrAddons);
				
				UniteProviderFunctionsUC::doAction("uc_export_category_addons", $catTitle);
			}
			
			//create zip file
			if(empty($filename)){
				if(count($arrCats) == 1)
					$filename = $catTitle;
				else
					$filename = self::MULTIPLE_FOLDERS_FILENAME;
			}
			
			UniteFunctionsUC::validateNotEmpty($filename,"export filename");
			
			if($runFunc === null){
				$this->prepareExportFolders_exportFilename($filename, $exportType);
				
				$this->makeExportCategoryZipFile();
				$this->downloadCategoryFile();
				exit();
			}else{
				call_user_func(array($this, $runFunc));
			}
			
			
		}catch(Exception $e){
		
			throw $e;
		}
		
	}
	
	private function a_______IMPORT_ADDON_______(){}
	
	/**
	 * validate that the temp file array
	 */
	private function validateArrTempFile($arrTempFile){
		
		$filename = UniteFunctionsUC::getVal($arrTempFile, "name");
		UniteFunctionsUC::validateNotEmpty($filename, "addon file name");
		
		$info = pathinfo($filename);
		$ext = UniteFunctionsUC::getVal($info, "extension");
		$ext = strtolower($ext);
		
		if($ext != "zip")
			UniteFunctionsUC::throwError("Wrong import addon file type: {$filename}, should be zip type only.");
		
	}
	
	
	/**
	 * prepare import addon folders
	 */
	private function prepareImportFolders(){
		
		//prepare import folder
		$this->prepareImportFolders_globalImport();
		
		if($this->isPathSingle == false){		//first path
			
			$pathImportBase = $this->pathImport."first/";
					
		}else{
			$pathImportBase = $this->pathImport."single/";
		}
		
		UniteFunctionsUC::mkdirValidate($pathImportBase, "import first");
		UniteFunctionsUC::deleteDir($pathImportBase, false);
		
		//create index.html
		UniteFunctionsUC::writeFile("", $pathImportBase."index.html");
		
		self::$serial++;
		
		$this->pathImportAddon = $pathImportBase."addon_".self::$serial."_".UniteFunctionsUC::getRandomString(10)."/";
		$this->pathImportAddonAssets = $this->pathImportAddon."assets/";
		
		UniteFunctionsUC::mkdirValidate($this->pathImportAddon, "import addon");
		
		
	}
	
	
	/**
	 * delete import addon folder
	 */
	private function deleteImportAddonFolder(){
	
		if(!empty($this->pathImportAddon) && is_dir($this->pathImportAddon))
			UniteFunctionsUC::deleteDir($this->pathImportAddon);
	}
	
	
	/**
	 * unpack import addon from temp file
	 */
	private function extractImportAddonFile($arrTempFile){
		
		$filepath = UniteFunctionsUC::getVal($arrTempFile, "tmp_name");
		
		$zip = new UniteZipUC();
		$extracted = $zip->extract($filepath, $this->pathImportAddon);
		
		if($extracted == false)
			UniteFunctionsUC::throwError("The import addon zip didn't extracted");
		
	}
	
	
	
	
	/**
	 * import templates
	 */
	private function importAddonData_addTemplates($arrImport, $addonData){
		
		//prepare templates data
		$templateNames = UniteFunctionsUC::getVal($arrImport, "templates");
		
		$arrTemplates = array();
		foreach($templateNames as $templateName){
		
			$filenameTemplate = $templateName.".tpl";
			$filepathTemplate = $this->pathImportAddon.$filenameTemplate;
			if(is_file($filepathTemplate) == false)
				UniteFunctionsUC::throwError("Template {$filenameTemplate} not found!");
		
			$templateContent = file_get_contents($filepathTemplate);
			$arrTemplates[$templateName] = $templateContent;
		}
		
		$addonData["templates"] = json_encode($arrTemplates);
		
		return($addonData);
	}

	
	/**
	 * add test data
	 */
	private function importAddonData_addDefaultData($addonData){
		
		$filenameTestData = "default_data.json";
		$filepathTestData = $this->pathImportAddon.$filenameTestData;
		
		if(file_exists($filepathTestData) == false)
			return($addonData);
		
		$arrContent = file_get_contents($filepathTestData);
		if(empty($arrContent))
			return($addonData);
		
		//check if the string is json (decode and encode again)
		$arrContent = UniteFunctionsUC::jsonDecode($arrContent);
		
		if(is_array($arrContent) == false)
			return($addonData);
		
		//add the default data (test_slot2)
			
		$jsonContent = json_encode($arrContent);
		
		$addonData["test_slot2"] = $jsonContent;
		
		return($addonData);
	}
	
	
	/**
	 * import addon data
	 */
	private function importAddonData($catID, $overwrite = true, $forceToCat = true){
		
		
		$filenameAddon = "addon.json";
		$filepathData = $this->pathImportAddon.$filenameAddon;
		
		
		if(is_file($filepathData) == false)
			UniteFunctionsUC::throwError("Addon import file: $filenameAddon don't found");
		
		$contents = file_get_contents($filepathData);
		
		if(empty($contents))
			UniteFunctionsUC::throwError("Empty import file {$filenameAddon} contents");
		
		$arrImport = @json_decode($contents);
		
		if(empty($arrImport))
			UniteFunctionsUC::throwError("Wrong import file {$filenameAddon} content");
			
		$arrImport = UniteFunctionsUC::convertStdClassToArray($arrImport);
		
		if(is_array($arrImport) == false)
			UniteFunctionsUC::throwError("Wrong addon import data, should be array");
		
		$addonName = UniteFunctionsUC::getVal($arrImport, "name");
		$addonType = UniteFunctionsUC::getVal($arrImport, "addontype");
		$addonAlias = UniteFunctionsUC::getVal($arrImport, "alias");
		$catTitle = UniteFunctionsUC::getVal($arrImport, "cattitle");
		$addonTitle = UniteFunctionsUC::getVal($arrImport, "title");		
				
		$isSpecialAddonType = HelperUC::isSpecialAddonType($addonType);
				
		
		//---- add log text ------
		
		$logTitle = $addonTitle;
		if(empty($logTitle))
			$logTitle = $addonName;
		
		$objAddonType = UniteCreatorAddonType::getAddonTypeObject($addonType);
		$txtSingle = $objAddonType->textSingle;
		if(empty($txtSingle))
			$txtSingle = "addon";
		
		$txtSingle = strtolower($txtSingle);
		
		$textLog = "$txtSingle $logTitle";
		
		//if empty addon type - set by the given type
		if(empty($addonType) && !empty($this->mustAddonType)){
			
			$addonType = $this->mustAddonType;
			
			if(empty($addonAlias))
				$addonAlias = $addonName;
			
			$addonName = $addonName."_".$addonType;
		}
		
		//check if the addon exists, if needed
		if($overwrite == false){
			
			$isExists = $this->objAddons->isAddonExistsByName($addonName);
			
			if($isExists == true){
				$textLog .= " skipped";
				$this->addLog($textLog);
				return(false);
			}
			
		}
		
		//check if addon type match
		if(!empty($this->mustAddonType) && $this->mustAddonType != $addonType){
			
			$textLog .= " wrong addon type, skipped";
			$this->addLog($textLog);
			return(false);
		}
		
		//import other addon types to blox, like from vc
		if(empty($this->mustAddonType) && !empty($addonType) && $isSpecialAddonType == false){
			$addonType = "";
			$addonName = $addonAlias;
			$addonAlias = "";
		}
		
		
		$objCategories = new UniteCreatorCategories();
		if($forceToCat == false){	//first addon category, then given category
			
			if(!empty($catTitle)){
				$catID = $objCategories->getCreateCatByTitle($catTitle, $addonType);
			}
		}else{	//force to category - first given cat, then addon cat
			if(empty($catID))
				$catID = $objCategories->getCreateCatByTitle($catTitle, $addonType);
		}
		
		if(empty($catID))
			$catID = 0;
		
		
		//prepare data
		$addonData = array();
		$addonData["name"] = $addonName;
		$addonData["alias"] = $addonAlias;
		$addonData["addontype"] = $addonType;
		$addonData["title"] = UniteFunctionsUC::getVal($arrImport, "title");
		$addonData["description"] = UniteFunctionsUC::getVal($arrImport, "description");
		$addonData["catid"] = $catID;
		
						
		$config = UniteFunctionsUC::getVal($arrImport, "config");
		if(is_array($config) == false)
			UniteFunctionsUC::throwError("Wrong addon config data");
			
		$addonData["config"] = json_encode($config);
		$addonData["is_active"] = true;
		
		//---- import templates ---- 
		
		$addonData = $this->importAddonData_addTemplates($arrImport, $addonData);
		
		// ------ import test data ----------
		
		$addonData = $this->importAddonData_addDefaultData($addonData);
		
		$objAddon = new UniteCreatorAddon();
		$isNewAdded = $objAddon->importAddonData($addonData);
		
		$this->lastImportedAddonID = $objAddon->getID();
		$this->lastImportedCatID = $catID;
		
		if($isNewAdded){
			$textLog .= " added";
			
			//make the last imported addons list
			self::$arrImportedAddons[$addonName] = true;
		}
		else
			$textLog .= " overwrited";
		
		$this->addLog($textLog);
		
		//save added type
		$this->importedAddonType = $addonType;
		
		return(true);
	}
	
	
	/**
	 * copy import assets folder
	 */
	private function copyImportAssetsFolder(){
		
		if(is_dir($this->pathImportAddonAssets) == false)
			return(false);
		
		$pathAssets = GlobalsUC::$pathAssets;
		
		if(!empty($this->importedAddonType)){
			$objAddonType = UniteCreatorAddonType::getAddonTypeObject($this->importedAddonType);
			$pathAssets = HelperUC::getAssetsPath($objAddonType);
		}
		
		
		UniteFunctionsUC::copyDir($this->pathImportAddonAssets, $pathAssets);
		
	}
	
	
	/**
	 * check if extracted addon single
	 */
	private function isExtractedAddonSingle(){
		
		if($this->isPathSingle == true)
			return(true);
		
		$filenameAddon = "addon.json";
		$filepathData = $this->pathImportAddon.$filenameAddon;
		
		if(file_exists($filepathData))
			return(true);
		
		return(false);
	}
	
	
	/**
	 * set import single type
	 */
	public function setImportSingleAddon(){
		
		$this->isPathSingle = true;
		
	}
	
	
	/**
	 * set must import addon type, the addons will be imported to this type
	 */
	public function setMustImportAddonType($addonType){
		
		if($addonType == GlobalsUC::ADDON_TYPE_REGULAR_ADDON)
			$this->mustAddonType = "";
		else
			$this->mustAddonType = $addonType;
		
	}
	
	
	/**
	 * import addon
	 * tempFile can be array or filepath
	 */
	public function import($catID, $arrTempFile, $overwrite = true, $forceToCat = true){
			
		if($this->isImportedOnce == true)
			UniteFunctionsUC::throwError("The import script can't run twice");
		
		$this->isImportedOnce = true;
		
		if(empty($catID) || is_numeric($catID) == false)
			$catID = 0;
				
		//crate array from filepath
		if(getType($arrTempFile) == "string"){
			$filepath = $arrTempFile;
			$arrInfo = pathinfo($filepath);
			$filename = UniteFunctionsUC::getVal($arrInfo, "basename");
			
			$arrTempFile = array();
			$arrTempFile["tmp_name"] = $filepath;
			$arrTempFile["name"] = $filename;
		}
		
		$this->validateArrTempFile($arrTempFile);
				
		try{
			
			$this->prepareImportFolders();
						
			$this->extractImportAddonFile($arrTempFile);
			
			$isSingle = $this->isExtractedAddonSingle();
			
			if($isSingle == true){
				
				$isImported = $this->importAddonData($catID, $overwrite, $forceToCat);
				
				if($isImported == true)
					$this->copyImportAssetsFolder();
			}else{
				$this->importAddonsFromFolder($this->pathImportAddon, $catID, $overwrite, true, $forceToCat);
			}
			
			$this->deleteImportAddonFolder();
			
			
		}catch(Exception $e){
			
			$this->deleteImportAddonFolder();
			
			throw $e;
		}
		
		$logText = $this->getLogText();
		return($logText);
	}
	
	/**
	 * get imported addon type
	 */
	public function getImportedAddonType(){
		
		return($this->importedAddonType);
	}
	
	/**
	 * get last imported addon id
	 */
	public function getImportedAddonID(){
		
		return($this->lastImportedAddonID);
	}
	
	/**
	 * get last imported cat id
	 */
	public function getImportedCatID(){
		
		return($this->lastImportedCatID);
	}
	
	/**
	 * get all imported addon names in this session
	 */
	public function getArrImportedAddonNames(){
		
		return(self::$arrImportedAddons);
		
	}
	
	private function a________BULK_IMPORT_________(){}
	
	
	/**
	 * get array of category data from some path
	 */
	protected function getCatagoryDataFromPath($path){
		
		$filepath = $path."category.json";
		
		if(file_exists($filepath) == false)
			return(null);
		
		$contents = file_get_contents($filepath);
		$arrData = UniteFunctionsUC::jsonDecode($contents);
		
		if(empty($arrData))
			$arrData = null;
		
		return($arrData);
	}
	
	
	/**
	 * get short log text (only from import addons from folder)
	 */
	public function getTextLogShort(){
		
		return($this->textLogShort);
	}
	
	/**
	 * import all addons from folder
	 */
	public function importAddonsFromFolder($path, $catIDParam = 0, $overwrite = false, $forceSingle = false, $forceToCat = true){
		
		if(is_dir($path) == false)
			return(false);
		
		if($catIDParam == "all" || empty($catIDParam))
			$catIDParam = null;
		
		$arrFiles = UniteFunctionsUC::getFileListTree($path, "zip");
		
		//make files with paths list
		$arrFilesFull = array();
		$arrCats = array();
				
		//create category from path if exists
		foreach($arrFiles as $file){
						
			$pathRelative = str_replace($path, "", $file);
						
			$parentDir = dirname($pathRelative);
			if($parentDir == ".")
				$parentDir = "";
			
			$info = pathinfo($pathRelative);
			
			if(strlen($parentDir) < 3)
				$parentDir = "";
						
			$item = array();
			$item["catname"] = $parentDir;
			$item["filepath"] = $file;
			
			
			//get category data
			if(!empty($parentDir)){
				
				$pathCategory = $path.$parentDir."/";
								
				$catData = $this->getCatagoryDataFromPath($pathCategory);
				
				$arrCats[$parentDir] = $catData;
			}
			
			$arrFilesFull[] = $item;
		}
				
				
		//create categories
		if(empty($catIDParam) || $forceToCat == false && !empty($arrCats)){
			
			$objCategories = new UniteCreatorCategories();
			
			$addonType = $this->mustAddonType;
			if(empty($addonType))
				$addonType = "";
			
			foreach($arrCats as $catname => $catData){
				
				$catAddonType = null;
				
				//check category addon type
				if(!empty($catData)){
					
					$catAddonType = UniteFunctionsUC::getVal($catData, "type");
					
					$isSpecialAddonType = HelperUC::isSpecialAddonType($catAddonType);
					
					//validate addon type
					if($isSpecialAddonType == false && $catAddonType != $addonType)
						UniteFunctionsUC::throwError("Wrong category addon type: ". $addonType);
					
					$catname = UniteFunctionsUC::getVal($catData, "title");
					UniteFunctionsUC::validateNotEmpty($catname,"category title from category.json");
				}
				
				if(empty($catAddonType))
					$catAddonType = $addonType;
				
				$catID = $objCategories->getCreateCatByTitle($catname, $catAddonType, $catData);
				
				//modify cat name for special addon types
				if($isSpecialAddonType)
					$catname = $catAddonType."_".$catname;
				
				$arrCats[$catname] = $catID;
			}
			
		}
		
		
		try{
			
			//update category type on the way
			$isAddonTypeUpdated = false;
			$addonType = "";
			
			foreach($arrFilesFull as $item){
				
				$catName = $item["catname"];
				$filepath = $item["filepath"];
				
				if(file_exists($filepath) == false)
					continue;

				$catID = UniteFunctionsUC::getVal($arrCats, $catName);
				if(empty($catID) || $forceToCat == true && !empty($catIDParam))
					$catID = $catIDParam;
				
				if(empty($catID))
					$catID = 0;
				
				$objImporter = new UniteCreatorExporter();
				$objImporter->setMustImportAddonType($this->mustAddonType);
				
				if($forceSingle == true)
					$objImporter->setImportSingleAddon();
				
				$logText = $objImporter->import($catID, $filepath, $overwrite, true);
				
				//update category type if not updated
				if($isAddonTypeUpdated == false){
					
					$addonType = $objImporter->getImportedAddonType();
										
					if(!empty($addonType) && !empty($catID)){
						$objCats = new UniteCreatorCategories();
						$objCats->updateType($catID, $addonType);
						
						$isAddonTypeUpdated = true;
					}
				}
				
				$this->addLog($logText);
				
			}
			
			$logText = $this->getLogText();
			
			//create categories short text
			$textCats = "";
			if(!empty($arrCats)){
				$arrCatNames = array_keys($arrCats);
				$this->textLogShort = "Installed ".implode(",", $arrCatNames);
				$numCats = count($arrCatNames);
				
				if($numCats == 1)
					$this->textLogShort .= " bundle";
				else 
					$this->textLogShort .= " bundles";
					
			}else{
				$numAddons = count($arrFilesFull);
				$this->textLogShort = "Installed ".$numAddons." addons";
			}
			
			
			return($logText);
			
		}catch(Exception $e){
			
			
			$message = $e->getMessage();
			
			$this->addLog("error: $message");
			
			throw $e;
						
		}
		
	}
	
	
	
}
