<?php
/**
 *---------------------------------------------------------------------------------------
 * @package       VirtuePlanet Framework for Joomla!
 *---------------------------------------------------------------------------------------
 * @copyright     Copyright (C) 2012-2021 VirtuePlanet Services LLP. All rights reserved.
 * @license       GNU General Public License version 2 or later; see LICENSE.txt
 * @authors       Abhishek Das
 * @email         info@virtueplanet.com
 * @link          https://www.virtueplanet.com
 *---------------------------------------------------------------------------------------
 */
defined ('_JEXEC') or die;

jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');
/**
 * VP Framework Template Class
 */
class VPFrameworkTemplate extends JObject
{
	/**
	* Public variables
	* 
	*/
	public $id;
	public $home;
	public $name;
	public $params;
	public $path;
	public $uri;
	public $template;
	public $media_path;
	public $media_uri;
	public $cproducts;
	public $wproducts;
	public $show_rating;
	public $selected_layout;
	public $structure_paths = array();
	public $html_paths = array();
	public $menu_paths = array();
	public $xml = null;
	public $framework_xml = null;

	/**
	* Protected variables
	* 
	*/
	protected $_options;
	protected $_google_fonts = array();

	/**
	* 
	* @var array Array of instances
	* 
	*/
	public static $instances = array();

	/**
	* Static variables
	* 
	*/
	protected static $menu = null;
	protected static $offcanvas = null;
	protected static $articleItemids = array();
	protected static $loadedJS = array();
	protected static $loadedCSS = array();
	protected static $scriptDeclarations = array();

	/**
	* Constructor for VPFrameworkTemplate
	* 
	* @param  mixed   (array/null) $options
	* 
	* @return void
	*/
	public function __construct($options = array())
	{
		$app               = JFactory::getApplication('site');
		$template          = $this->_getTemplate(true);
		
		$this->name        = $template->template;
		$this->path        = JPath::clean(JPATH_SITE . '/templates/' . $this->name);
		$this->uri         = JUri::base(true) . '/templates/' . $this->name;
		$this->media_path  = JPath::clean(JPATH_SITE . '/media/vpframework');
		$this->media_uri   = JUri::base(true) . '/media/vpframework';
		$this->_options    = $options;
		
		$params            = $this->getFrameworkDefaultParams();
		$params->merge($template->params);
		$this->params      = $params;
		
		$vm_field_colors = trim($this->params->get('vm_field_colors', ''));

		if(!empty($vm_field_colors) && strpos($vm_field_colors, ':'))
		{
			$vm_field_colors = (strpos($vm_field_colors, ',') !== false) ? explode(',', $vm_field_colors) : (array) $vm_field_colors;
			$colors = array();
			
			foreach($vm_field_colors as $mapping)
			{
				if(strpos($mapping, ':'))
				{
					$mapping = explode(':', $mapping);
					$value = trim($mapping[0]);
					$color = trim($mapping[1]);
					$colors[$value] = $color;
				}
			}
			
			$this->params->set('vm_field_colors', $colors);
		}
		else
		{
			$this->params->set('vm_field_colors', array());
		}

		if($this->params->get('vpframework', 0))
		{
			$this->id = $template->id;
			$this->home = $template->home;
			
			if($layouts = $this->getLayouts())
			{
				$layouts_path = $this->path . '/layouts';
				
				if(in_array('default', $layouts))
				{
					$this->selected_layout = 'default';
					$default_layout_path = $layouts_path . '/default';
					$this->addStructurePath($default_layout_path);
					$this->addHTMLPath($default_layout_path . '/html');
					$this->addMenuPath($default_layout_path . '/menu');
				}
				
				$custom_layout = $this->params->get('layout', 'default');
				
				if($custom_layout != 'default' && in_array($custom_layout, $layouts))
				{
					$this->selected_layout = $custom_layout;
					$custom_layout_path = $layouts_path . '/' . $custom_layout;
					$this->addStructurePath($custom_layout_path);
					$this->addHTMLPath($custom_layout_path . '/html');
					$this->addMenuPath($custom_layout_path . '/menu');
				}
			}
		}
	}
	
	public static function getInstance($options = array())
	{
		$options = (array) $options;
		$hash = md5(serialize($options));

		if (isset(self::$instances[$hash]))
		{
			return self::$instances[$hash];
		}

		self::$instances[$hash] = new VPFrameworkTemplate($options);
		
		return self::$instances[$hash];
	}

	/**
	* Method to get the active site template
	* 
	* @param boolean $fullData  True of only name
	* 
	* @return
	*/
	protected function _getTemplate($fullData = false)
	{
		$app = JFactory::getApplication();
		$option = $app->input->getCmd('option', '');
		
		if($app->isAdmin())
		{
			$template_id = 'default';
			
			if($option == 'com_virtuemart')
			{
				JLoader::register('VmConfig', JPATH_ROOT . '/administrator/components/com_virtuemart/helpers/config.php');
				VmConfig::loadConfig();
				$template_id = VmConfig::get('vmtemplate', 'default');
			}
			
			if($template_id == 'default' || empty($template_id))
			{
				$helper = plgSystemVPFrameworkHelper::getInstance();
				$template = $helper->getDefaultTemplate();
			}
			else
			{
				$helper = VPFrameworkAdmin::getInstance(array('id' => (int) $template_id));
				$template = $helper->getTemplate();
			}

			if(!empty($template->template))
			{
				$this->template = $template->template;
			}
			
			if(!$fullData && !empty($template->template))
			{
				return $template->template;
			}
			
			if(!empty($template) && !empty($template->params))
			{
				$temp = new JRegistry;
				$temp->loadString($template->params);
				$template->params = $temp;
			}
			
			return $template;
		}
		else
		{
			$template = $app->getTemplate($fullData);
			
			if(is_object($template) && !empty($template->template))
			{
				$this->template = $template->template;
			}
			
			return $template;
		}
	}
	
	/**
	* Magic method to get the Site template name
	* 
	* @return string Template name
	*/
	public function __toString()
	{
		return $this->_getTemplate();
	}
	
	public function getXml()
	{
		if($this->xml === null)
		{
			$xmlPath = JPath::clean($this->path . '/templateDetails.xml');
			$this->xml = JFactory::getXML($xmlPath);
		}
		
		return $this->xml;
	}
	
	public function getFormsToSkip($type = 'params', $fullPath = true)
	{
		$xml = $this->getXml();
		$result = array();
		
		if($xml instanceof JXMLElement && !empty($xml->ignores))
		{
			if(!empty($xml->ignores->$type))
			{
				$ignores = (array) $xml->ignores->$type;
				
				if(!$fullPath)
				{
					return $ignores;
				}
				
				$path = ($type == 'params') ? VPF_PLUGINPATH . '/forms/params' : VPF_PLUGINPATH . '/forms';
				
				foreach($ignores as $ignore)
				{
					$file = JPath::clean($path . '/' . $ignore . '.xml');
					if(JFile::exists($file))
					{
						$result[] = $file;
					}
				}
			}
		}
		
		return $result;
	}
	
	protected function getFrameworkDefaultParams()
	{
		$XMLfiles = JFolder::files(VPF_PLUGINPATH . '/forms/params', '\.xml', false, true);
		$params = new JRegistry;
		
		if(empty($XMLfiles))
		{
			return $params;
		}
		
		$paramsToSkip = $this->getFormsToSkip();
		// Creating the data collection variable:
		$config = array();
		
		foreach($XMLfiles as $XMLfile)
		{
			$XMLfile = JPath::clean($XMLfile);
			
			if(in_array($XMLfile, $paramsToSkip))
			{
				continue;
			}
			
			if(!file_exists($XMLfile))
			{
				$this->setError($XMLfile . ' file not found');
				return false;
			}
			
			$manifest = simplexml_load_file($XMLfile);
			
			if (!isset($manifest->fields))
			{
				continue;
			}
			
			foreach($manifest->fields as $fields)
			{
				if($fields->attributes()->name == 'params' && isset($fields->fieldset))
				{
					// Getting the fieldset tags
					$fieldsets = $fields->fieldset;

					// Iterating through the fieldsets:
					foreach ($fieldsets as $fieldset)
					{
						if (!count($fieldset->children()))
						{
							// Either the tag does not exist or has no children therefore we return zero files processed.
							continue;
						}

						// Iterating through the fields and collecting the name/default values:
						foreach ($fieldset as $field)
						{
							// Check against the null value since otherwise default values like "0"
							// cause entire parameters to be skipped.
							if (($name = $field->attributes()->name) === null)
							{
								continue;
							}
							
							if (in_array($field->attributes()->type, array('spacer', 'groupheading')))
							{
								continue;
							}
							
							$value = $field->attributes()->default;
							
							$value = (string) $value;
							
							if(strpos($value, ','))
							{
								$value = explode(',', $value);
							}
							
							$config[(string) $name] = $value;
						}
					}
				}
			}
		}
	
		$params->loadArray($config);
		return $params;
	}

	
	public function getLayouts()
	{
		$layouts_path = $this->path . '/layouts';
		
		if (!is_dir($layouts_path)) 
		{
			JError::raiseWarning(21, 'VPFrameworkTemplate::getLayouts: ' . JText::_('PATH_IS_NOT_A_FOLDER'), 'Path: ' . $layouts_path);
			return false;
		}
		
		$layouts = JFolder::folders($layouts_path, '.', false, false);
		
		if(empty($layouts))
		{
			JError::raiseWarning(21, 'VPFrameworkTemplate::getLayouts: No Template layouts found at Path: ' . $layouts_path);
			return false;
		}
		
		return $layouts;
	}
	
	public function addHTMLPath($path)
	{
		$path = (string) $path;
		
		if(!in_array($path, $this->html_paths))
		{
			$this->html_paths[] = JPath::clean($path);
		}
	}
	
	public function addStructurePath($path)
	{
		$path = (string) $path;
		
		if(!in_array($path, $this->structure_paths))
		{
			$this->structure_paths[] = JPath::clean($path);
		}
	}
	
	public function addMenuPath($path)
	{
		$path = (string) $path;
		
		if(!in_array($path, $this->menu_paths))
		{
			$this->menu_paths[] = JPath::clean($path);
		}
	}
	
	public function getHTMLLayout($file)
	{
		$file = JPath::clean($file);
		$template_path = JPath::clean($this->path . '/html');
		$relative_path = str_replace($template_path, '', $file);

		if(!empty($this->html_paths))
		{
			$html_paths = array_reverse($this->html_paths);

			// Special case only for frontend edit
			if($this->_isFrontendEdit())
			{
				$parts = pathinfo($relative_path);
				$fe_relative_path = JPath::clean($parts['dirname'] . '/' . $parts['filename'] . '.fee.' . $parts['extension']);
				
				// Fix VirtueMart Front
				foreach($html_paths as $html_path)
				{
					$file_path = JPath::clean($html_path . $fe_relative_path);
					
					if(is_file($file_path))
					{
						return $file_path;
					}
				}
			}
			
			foreach($html_paths as $html_path)
			{
				$file_path = JPath::clean($html_path . $relative_path);

				if(file_exists($file_path))
				{
					if(strpos($file_path, 'virtuemart'))
					{
						VPFrameworkVM::onLayoutCall($file_path);
					}
					
					return $file_path;
				}
			}
		}

		JError::raiseError(500, JText::sprintf('TMPL_VPFRAMEWORK_ERROR_HTML_NOT_FOUND', $file));
		return false;
	}
	
	public function loadView($view)
	{
		if(!is_object($view))
		{
			return null;
		}
		
		$output = $view->loadTemplate();
		
		if($output instanceof Exception)
		{
			return $output;
		}

		echo $output;
	}

	public function getStructure($file)
	{
		$file = JPath::clean($file);
		$relative_path = str_replace($this->path, '', $file);
		
		if(!empty($this->structure_paths))
		{
			$structure_paths = array_reverse($this->structure_paths);
			
			// Special case only for frontend edit
			if($this->_isFrontendEdit())
			{
				$parts = pathinfo($relative_path);
				$fe_relative_path = JPath::clean($parts['dirname'] . '/' . $parts['filename'] . '.fee.' . $parts['extension']);
				foreach($structure_paths as $structure_path)
				{
					$file_path = JPath::clean($structure_path . $fe_relative_path);
					
					if(is_file($file_path))
					{
						return $file_path;
					}
				}
			}
			
			// Find and return the respective structure file from template layouts
			foreach($structure_paths as $structure_path)
			{
				$file_path = JPath::clean($structure_path . $relative_path);
				
				if(is_file($file_path))
				{
					return $file_path;
				}
			}
		}
		
		JError::raiseError(500, JText::sprintf('TMPL_VPFRAMEWORK_ERROR_STRUCTURE_NOT_FOUND', $file));
		return false;
	}
	
	public function _isFrontendEdit()
	{
		$app        = JFactory::getApplication();
		$option     = strtolower($app->input->getCmd('option'));
		$view       = strtolower($app->input->getCmd('view'));
		$task       = strtolower($app->input->getCmd('task'));
		$manage     = strtolower($app->input->getInt('manage'));
		$components = array('com_config', 'com_contenthistory', 'com_media');

		return $app->isSite() && (in_array($option, $components) || ($option == 'com_virtuemart' && $manage)) || ($option == 'com_flexicontent' && $task == 'edit');
	}

	public function getMenuLayout($layout = 'default')
	{
		if(!empty($this->menu_paths))
		{
			$menu_paths = array_reverse($this->menu_paths);

			// Special case only for frontend edit
			if($this->_isFrontendEdit())
			{
				foreach($menu_paths as $menu_path)
				{
					$file_path = JPath::clean($menu_path . '/' . $layout . '.fee.php');
					
					if(is_file($file_path))
					{
						return $file_path;
					}
				}
			}
			
			foreach($menu_paths as $menu_path)
			{
				$file_path = JPath::clean($menu_path . '/' . $layout . '.php');
				
				if(is_file($file_path))
				{
					return $file_path;
				}
			}
		}
		
		JError::raiseError(500, JText::sprintf('TMPL_VPFRAMEWORK_ERROR_MENU_NOT_FOUND', $file));
		return false;
	}
	
	public function loadBlock($name)
	{
		if(!empty($this->structure_paths))
		{
			$structure_paths = array_reverse($this->structure_paths);

			foreach($structure_paths as $structure_path)
			{
				$file_path = JPath::clean($structure_path . '/blocks/' . strtolower($name) . '.php');
				
				if(is_file($file_path))
				{
					return $file_path;
				}
			}
		}
		
		JError::raiseError(500, JText::sprintf('TMPL_VPFRAMEWORK_ERROR_FILE_NOT_FOUND', $name));
		return false;
	}
	
	public function addFrameworkScript($responsive = true, $minWidth = '1200')
	{
		if(!$this->_isFrontendEdit())
		{
			JHtml::_('jquery.framework');
			$doc = JFactory::getDocument();
			$tab = $doc->_getTab();
			$lineEnd = $doc->_getLineEnd();
			
			$this->addScript('vpframework/modernizr.min.js', $this->getFrameworkVersion());
			
			if(VPFrameworkUtility::hasExtension('com_virtuemart', 'component'))
			{
				VPFrameworkVM::loadjQueryUI();
			}
			
			$this->addScript('vpframework/bootstrap.min.js', $this->getFrameworkVersion());
			$this->addScript('vpframework/vpframework.min.js', $this->getFrameworkVersion());
		}
		else
		{
			JHtml::_('bootstrap.framework');
			$this->addScript('vpframework/frontend.edit.js', $this->getFrameworkVersion());
		}
	}

	public function addFrameworkCSS($responsive = true, $minWidth = '1200')
	{
		if(!$this->_isFrontendEdit())
		{
			$this->addStylesheet('vpframework/bootstrap.min.css', $this->getFrameworkVersion());
			
			if(!$responsive)
			{
				$minWidth = ($minWidth == '1200') ? '1200' : '980';
				
				$this->addStylesheet('vpframework/bootstrap.unresponsive.' . $minWidth . '.min.css', $this->getFrameworkVersion());
			}
			
			$iconSet = $this->params->get('vpficon', 'icons');
			
			if($iconSet == 'font-awesome' || $iconSet == 'fa')
			{
				$this->addStylesheet('vpframework/font-awesome.css', $this->getFrameworkVersion());
			}
			else
			{
				$this->addStylesheet('vpframework/icons.css', $this->getFrameworkVersion());
			}
			
			$this->addStylesheet('vpframework/animate.css', $this->getFrameworkVersion());
			
			if(VPFrameworkUtility::hasExtension('com_virtuemart', 'component'))
			{
				VPFrameworkVM::setColorFieldsCSS($this->params);
			}
		}
		else
		{
			$doc = JFactory::getDocument();
			
			$this->addStylesheet('vpframework/frontend.edit.css', $this->getFrameworkVersion());
			
			JHtml::_('bootstrap.loadCss', false, $doc->direction);
		}
	}
	
	public function loadFramework($responsive = true, $minWidth = '1200')
	{
		$this->addFrameworkScript($responsive, $minWidth);
		$this->addFrameworkCSS($responsive, $minWidth);
	}
	
	public function addScriptDeclaration($js, $unique_name = null)
	{
		$doc = JFactory::getDocument();
		
		if(empty($unique_name))
		{
			$doc->addScriptDeclaration($js);
		}
		elseif(!isset(self::$scriptDeclarations[$unique_name]))
		{
			self::$scriptDeclarations[$unique_name] = $js;
			$doc->addScriptDeclaration($js);
		}
	}
	
	public function loadSpecialCSS()
	{
		jimport('joomla.filesystem.folder');
		jimport('joomla.filesystem.file');
		
		$doc             = JFactory::getDocument();
		$theme           = $this->params->get('theme', 'default');
		$theme_path      = $this->path . '/css/themes/' . $theme . '.css';
		$custom_css_dir  = $this->path . '/css/custom';
		$valid_theme     = JFile::exists($theme_path);
		
		if(!$valid_theme)
		{
			return;
		}
		
		$this->addStylesheet('themes/' . $theme . '.css', $this->getVersion());
		
		$customs = JFolder::files($custom_css_dir, '\.css');
		
		if(!empty($customs))
		{
			foreach($customs as $custom)
			{
				$name = preg_replace('/\\.[^.\\s]{3,4}$/', '', $custom);
				
				if(strpos($name, '.'))
				{
					$parts = explode('.', $name);
					
					if($parts[0] == $theme)
					{
						$this->addStylesheet('custom/' . $custom, $this->getVersion());
					}
				}
				else
				{
					$this->addStylesheet('custom/' . $custom, $this->getVersion());
				}
			}
		}
	}
	
	public function loadSpecialJS()
	{
		jimport('joomla.filesystem.folder');
		jimport('joomla.filesystem.file');
		
		$doc             = JFactory::getDocument();
		$theme           = $this->params->get('theme', 'default');
		$theme_path      = $this->path . '/css/themes/' . $theme . '.css';
		$custom_js_dir   = $this->path . '/js/custom';
		$valid_theme     = JFile::exists($theme_path);
		$has_custom_js   = JFolder::exists($custom_js_dir);
		
		if(!$valid_theme || !$has_custom_js)
		{
			return;
		}
		
		$customs = JFolder::files($custom_js_dir, '\.js');
		
		if(!empty($customs))
		{
			foreach($customs as $custom)
			{
				$name = preg_replace('/\\.[^.\\s]{2,3}$/', '', $custom);

				if(strpos($name, '.'))
				{
					$parts = explode('.', $name);
					
					if($parts[0] == $theme)
					{
						$this->addScript('custom/' . $custom, $this->getVersion());
					}
				}
				else
				{
					$this->addScript('custom/' . $custom, $this->getVersion());
				}
			}
		}
	}
	
	public function loadBootSelect()
	{
		JHtml::script('vpframework/bootstrap-select.min.js', false, true);
		JHtml::stylesheet('vpframework/bootstrap-select.min.css', array(), true);
	}
	
	public function loadJSLibraries($libraries = array())
	{
		$libraries = (array) $libraries;
		$this->loadCSSLibraries($libraries);
		
		if(!empty($libraries))
		{
			foreach($libraries as $library)
			{
				$filename = trim($library) . '.js';
				
				if(strpos($library, 'jquery.owl.carousel') !== false && $this->params->get('owlcarousel_version', 0) == 2)
				{
					$filename = 'owl-carousel2/' . $filename;
				}
				
				$file = $this->media_path . '/js/' . $filename;
				
				if(!in_array($filename, static::$loadedJS) && file_exists($file))
				{
					$this->addScript('vpframework/' . $filename, $this->getFrameworkVersion());
					
					static::$loadedJS[] = $filename;
				}
			}
		}
	}
	
	public function loadCSSLibraries($libraries = array())
	{
		$libraries = (array) $libraries;
		
		if(!empty($libraries))
		{
			foreach($libraries as $library)
			{
				$filename = trim($library) . '.css';
				
				if(strpos($library, 'jquery.owl.carousel') !== false && $this->params->get('owlcarousel_version', 0) == 2)
				{
					$filename = 'owl-carousel2/' . $filename;
				}
				
				$file = $this->media_path . '/css/' . $filename;
				
				if(!in_array($filename, static::$loadedCSS) && file_exists($file))
				{
					$this->addStylesheet('vpframework/' . $filename, $this->getFrameworkVersion());

					static::$loadedCSS[] = $filename;
				}
			}
		}
	}
	
	public function getMenu()
	{
		if(static::$menu === null)
		{
			$params       = $this->params;
			$list         = VPFrameworkMenu::getList($params);
			$base         = VPFrameworkMenu::getBase($params);
			$active       = VPFrameworkMenu::getActive($params);
			$active_id    = $active->id;
			$path         = $base->tree;
			$tmpl         = '';
			$showAll      = $params->get('showAllChildren');

			if(count($list))
			{
				ob_start();
				require $this->getMenuLayout();
				$tmpl = ob_get_contents();
				ob_end_clean();
			}
			
			static::$menu = $tmpl;
		}
		
		return static::$menu;
	}
	
	public function getOffcanvas()
	{
		if(static::$offcanvas === null)
		{
			$params      = $this->params;
			$list        = VPFrameworkMenu::getOffCanvasMenu($params);
			$base        = VPFrameworkMenu::getBase($params);
			$active      = VPFrameworkMenu::getActive($params);
			$active_id   = $active->id;
			$path        = $base->tree;
			$tmpl        = '';
			$showAll     = $params->get('offcavas_showAllChildren');

			if(count($list))
			{
				ob_start();
				require $this->getMenuLayout('offcanvas');
				$tmpl = ob_get_contents();
				ob_end_clean();
			}
			
			static::$offcanvas = $tmpl;
		}
		
		return static::$offcanvas;
	}
	
	public function renderComparePage()
	{
		JLoader::register('VmConfig', JPATH_ROOT . '/administrator/components/com_virtuemart/helpers/config.php');
		JLoader::register('CurrencyDisplay', JPATH_ROOT . '/administrator/components/com_virtuemart/helpers/currencydisplay.php');

		VmConfig::loadConfig();
		VmConfig::loadJLang('com_virtuemart', true);
		JFactory::getLanguage()->load('tpl_vp_smart');
		
		
		$currency = CurrencyDisplay::getInstance();
		$layout   = JPath::clean($this->path . '/html/com_virtuemart/compare/default.php');
		
		if(is_file($layout))
		{
			$this->cproducts   = VPFrameworkVM::getCompareList();
			
			$ratingModel       = VmModel::getModel('ratings');
			$this->show_rating = $ratingModel->showRating();
			
			ob_start();
			require $layout;
			$tmpl = ob_get_contents();
			ob_end_clean();
			
			return $tmpl;
		}
		
		return null;
	}
	
	public function renderWishlistPage()
	{
		JLoader::register('VmConfig', JPATH_ROOT . '/administrator/components/com_virtuemart/helpers/config.php');
		JLoader::register('CurrencyDisplay', JPATH_ROOT . '/administrator/components/com_virtuemart/helpers/currencydisplay.php');

		VmConfig::loadConfig ();
		VmConfig::loadJLang('com_virtuemart', true);
		
		$currency = CurrencyDisplay::getInstance();
		$layout   = JPath::clean($this->path . '/html/com_virtuemart/wishlist/default.php');
		
		if(is_file($layout))
		{
			$this->wproducts   = VPFrameworkVM::getWishlist();
			
			$ratingModel       = VmModel::getModel('ratings');
			$this->show_rating = $ratingModel->showRating();
			
			ob_start();
			require $layout;
			$tmpl = ob_get_contents();
			ob_end_clean();
			
			return $tmpl;
		}
		
		return null;
	}
	
	public function getArticleItemid($article_id)
	{
		if(!isset(static::$articleItemids[$article_id]))
		{
			$app = JFactory::getApplication(); 
			$lang = JFactory::getLanguage();
			$language = $lang->getTag();
			$menus = $app->getMenu('site');
			$component = JComponentHelper::getComponent('com_content');

			$attributes = array('component_id');
			$values = array($component->id);

			$attributes[] = 'language';
			$values[] = array($language, '*');

			$items = $menus->getItems($attributes, $values);

			if(!empty($items))
			{
				if(count($items) == 1)
				{
					return $items[0]->id;
				}
				
				$lastCategoryID = null;
				
				foreach($items as $item)
				{
					$query = $item->query;
					
					if((isset($query['id']) && isset($query['view'])) && ($query['view'] == 'article') && ($query['id'] == $article_id))
					{
						$return = $item->id;
					}
				}
			}
			
			if(empty($return))
			{
				$default = $menus->getDefault($language);
				$return = !empty($default->id) ? $default->id : 0;
			}
			
			static::$articleItemids[$article_id] = $return;
		}
		
		return static::$articleItemids[$article_id]; 
	}
	
	public function getValidGridSize($size, $device = 'md')
	{
		$size = (int) $size;
		$device = trim((string) $device);
		$valid = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
		
		if(in_array($size, $valid))
		{
			return 'col-' . $device . '-' . $size;
		}
		
		return 'hidden-' . $device;
	}
	
	public function addHTMLClass($html, $element_type, $newClass)
	{
		if(empty($html) || !is_string($html))
		{
			return $html;
		}
		
		$dom = new DOMDocument;
		$dom_state = libxml_use_internal_errors(true);
		$meta = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
		$dom->loadHTML($meta . $html);
		libxml_clear_errors();
		libxml_use_internal_errors($dom_state);
		$elements = $dom->getElementsByTagName($element_type);
		
		if(!$elements->length)
		{
			return $html;
		}
		
		foreach($elements as $element)
		{
			$class = $element->getAttribute('class') ? $element->getAttribute('class') . ' ' . $newClass : $newClass;
			$element->setAttribute('class', $class);
		}
		
		$html = $dom->saveHTML();
		$html = preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $html);
		$html = str_replace($meta, '', $html);
		unset($dom, $elements, $element);
		
		return $html;
	}

	public function parseRadioList($html)
	{
		if(empty($html) || !is_string($html))
		{
			return $html;
		}
		
		$dom = new DOMDocument;
		$dom_state = libxml_use_internal_errors(true);
		$meta = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
		$dom->loadHTML($meta . $html);
		libxml_clear_errors();
		libxml_use_internal_errors($dom_state);
		$labels = $dom->getElementsByTagName('label');
		
		if(!$labels->length)
		{
			return $html;
		}
		
		$html = '';
		
		foreach($labels as $label)
		{
			$for = $label->getAttribute('for');
			$id = $label->getAttribute('id');
			$html .= '<div class="radio">';
			$html .= '<label for="' . $for . '" id="' . $id . '">';
			
			$innerHTML = ''; 
			$children = $label->childNodes;
			
			if($children->length)
			{
				foreach($children as $child) 
				{
					$temp = preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $label->ownerDocument->saveHTML($child));
					$innerHTML .= str_replace($meta, '', $temp);
				}
			}

			$html .= $innerHTML;
			$html .= '</label>';
			$html .= '</div>';
		}

		unset($dom, $labels, $label);
		
		return $html;
	}
	
	public function getCleanExternalURL($url)
	{
		$url = trim($url);
		
		if($url && pathinfo($url, PATHINFO_EXTENSION) && substr($url, 0, 4) != 'http')
		{
			$url = 'http://' . $url;
		}
		
		return $url; 
	}
	
	public function addGoogleFontFamily($fontName, $fontVariant, $fontSubsets)
	{
		if(empty($fontName))
		{
			return;
		}
		
		if(isset($this->_google_fonts[$fontName]))
		{
			$family = $this->_google_fonts[$fontName];
		}
		else
		{
			$family = new stdClass;
			
			$family->name = $fontName;
			$family->variants = array();
			$family->subnets = array();
		}
		
		if(!in_array($fontVariant, $family->variants))
		{
			$family->variants[] = $fontVariant;
		}
		
		if(!empty($fontSubsets))
		{
			if(empty($family->subnets))
			{
				$family->subnets = $fontSubsets;
			}
			else
			{
				foreach($fontSubsets as $fontSubset)
				{
					if(!in_array($fontSubset, $family->subnets))
					{
						$family->subnets[] = $fontSubset;
					}
				}
			}
		}
		
		$this->_google_fonts[$fontName] = $family;
	}
	
	public function getGoogleFontUrl()
	{
		if(empty($this->_google_fonts))
		{
			return false;
		}
		
		$family = array();
		$subnet = array();
		$aruments = array();
		
		foreach($this->_google_fonts as $font)
		{
			$temp = trim($font->name);
			
			if(!empty($font->variants))
			{
				$temp .= ':' . trim(implode(',', $font->variants));
			}
			
			$family[] = $temp;
			$subnet = array_merge($subnet, $font->subnets);
		}
		
		$base_url = '//fonts.googleapis.com/css';
		
		$scheme = VPFrameworkUrl::getInstance()->getScheme();
		
		if($scheme == 'http' || $scheme == 'https')
		{
			$base_url = $scheme . ':' . $base_url;
		}

		$aruments['family']= implode('|', $family);
		
		if(!empty($subnet))
		{
			$aruments['subnet'] = implode(',', $subnet);
		}
		
		$url = $base_url . '?' . http_build_query($aruments, null, '&', PHP_QUERY_RFC1738);
		
		return $url;
	}
	
	public function getGoogleFontFamily($name, $variants = null, $subsets = null)
	{
		$family = array();
		$family[] = str_replace(' ', '+', trim($name));
		
		if(!empty($variants))
		{
			if(is_array($variants))
			{
				$variants = array_map('trim', $variants);
				$family[] = implode(',', $variants);
			}
			else
			{
				$family[] = trim($variants);
			}
		}
		
		if(!empty($subsets))
		{
			if(is_array($subsets))
			{
				$subsets = array_map('trim', $subsets);
				$family[] = implode(',', $subsets);
			}
			else
			{
				$family[] = trim($subsets);
			}
		}
		
		$family = implode(':', $family);
		return $family;
	}
	
	public function getGoogleFontCSS($for, $name, $variants = null, $defaultFont = '')
	{
		$doc = JFactory::getDocument();
		$helper = VPFrameworkAdmin::getInstance();
		$tab = $doc->_getTab();
		$lineEnd = $doc->_getLineEnd();
		$font = $helper->getGoogleFont($name, false);
		
		if(empty($font))
		{
			return '';
		}
		
		$default = !empty($font['category']) ? ', ' . $font['category'] : '';
		$default = !empty($defaultFont) ? ', ' . $defaultFont . $default : '' . $default;
		
		if(is_array($variants))
		{
			foreach($variants as $variant)
			{
				$fontWeight = filter_var($variant, FILTER_SANITIZE_NUMBER_INT);
				
				if($fontWeight)
				{
					break;
				}
			}
		}
		else
		{
			$fontWeight = filter_var($variants, FILTER_SANITIZE_NUMBER_INT);
		}
		
		$css  = ($for == 'body') ?  $tab . $tab . 'body {' . $lineEnd : $tab . $tab . 'h1, h2, h3, h4, h5 {' . $lineEnd;
		$css .= $tab . $tab . $tab . 'font-family: \'' . $name . '\'' . $default . ';' . $lineEnd;
		
		if($fontWeight > 0)
		{
			$css .= $tab . $tab . $tab . 'font-weight: ' . $fontWeight . ';' . $lineEnd;
		}
		
		$css .= $tab . $tab . '}';
		
		return $css;
	}
	
	public function getGoogleFontJS($families)
	{
		if(empty($families))
		{
			return '';
		}

		$doc = JFactory::getDocument();
		$tab = $doc->_getTab();
		$lineEnd = $doc->_getLineEnd();
		
		$js  = $lineEnd;
		$js .= $tab . $tab . 'WebFontConfig = {' . $lineEnd;
		$js .= $tab . $tab . $tab . 'google: {' . $lineEnd;
		$js .= $tab . $tab . $tab . $tab . 'families: [' . $families . ']' . $lineEnd;
		$js .= $tab . $tab . $tab . '}' . $lineEnd;
		$js .= $tab . $tab . '};' . $lineEnd;
		$js .= $tab . $tab . '(function() {' . $lineEnd;
		$js .= $tab . $tab . $tab . 'var wf = document.createElement(\'script\');' . $lineEnd;
		$js .= $tab . $tab . $tab . 'wf.src = (\'https:\' == document.location.protocol ? \'https\' : \'http\') + \'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js\';' . $lineEnd;
		$js .= $tab . $tab . $tab . 'wf.type = \'text/javascript\';' . $lineEnd;
		$js .= $tab . $tab . $tab . 'wf.async = \'true\';' . $lineEnd;
		$js .= $tab . $tab . $tab . 'var s = document.getElementsByTagName(\'script\')[0];' . $lineEnd;
		$js .= $tab . $tab . $tab . 's.parentNode.insertBefore(wf, s);' . $lineEnd;
		$js .= $tab . $tab . '})();' . $lineEnd . $lineEnd;
		
		return $js;
	}
	
	public function getCleanImageURL($url, $absolute = false)
	{
		$url = trim($url);
		if(empty($url))
		{
			return $url;
		}
		elseif((JUri::root() != '' && strpos($url, JUri::root()) === 0) || (JUri::root(true) != '' && strpos($url, JUri::root(true)) === 0))
		{
			return $url;
		}
		elseif(strpos($url, 'http') === 0 || strpos($url, '//') === 0)
		{
			return $url;
		}
		else
		{
			$prefix = $absolute ? JUri::root() : JUri::root(true) . '/';
			return $prefix . $url;
		}
	}
	
	public function getLogoImage($image)
	{
		if(empty($image) || !JLanguageMultilang::isEnabled())
		{
			return $image;
		}
		
		$lang             = JFactory::getLanguage();
		$present_language = $lang->getTag();
		$default_language = $lang->getDefault();
		
		/*
		if($present_language == $default_language)
		{
			return $image;
		}
		*/

		$path_parts = @pathinfo($image);

		if(empty($path_parts['filename']) || empty($path_parts['dirname']) || empty($path_parts['extension']))
		{
			return $image;
		}
		
		$file_name = $path_parts['filename'] . '-' . strtolower($present_language) . '.' . $path_parts['extension'];
		$file      = $path_parts['dirname'] . '/' . rawurlencode($file_name);
		$file_path = JPath::clean(JPATH_SITE . '/' . $path_parts['dirname'] . '/' . $file_name);

		if(file_exists($file_path))
		{
			$image = $file;
		}

		return $this->cleanURL($image);
	}
	
	public function cleanURL($path)
	{
		if(JPATH_SITE && strpos($path, JPATH_SITE) === 0)
		{
			$path = substr_replace($path, '', strpos($path, JPATH_SITE), (strlen(JPATH_SITE) + 1));
		}
		elseif(JPATH_ADMINISTRATOR && strpos($path, JPATH_ADMINISTRATOR) === 0)
		{
			$path = substr_replace($path, '', strpos($path, JPATH_ADMINISTRATOR), (strlen(JPATH_ADMINISTRATOR) + 1));
		}
		
		$url = str_replace('\\', '/', $path);
		$url = preg_replace('/(\/+)/', '/', $url);

		return trim($url);
	}
	
	public function getCaptchaField($id = 'dynamic_recaptcha_1', $class = '')
	{
		$html = '';
		
		if(!JFactory::getUser()->get('guest'))
		{
			return $html;
		}
		
		// Import captcha plugin group
		JPluginHelper::importPlugin('captcha');
		
		// Get an instance of the dispatcher
		$dispatcher = JDispatcher::getInstance();
		
		$class = !empty($class) ? str_replace(array('class="', '"'), array('', ''), $class) : $class;
		$class = !empty($class) ? trim($class) : $class;
		$class = !empty($class) ? 'class="' . $class . '"' : 'class="captcha-required"';

		// Get the html from captcha plugin
		$results = $dispatcher->trigger('onDisplay', array(null, $id, $class));
		
		foreach($results as $result)
		{
			if($result && is_string($result))
			{
				$html = $result;
				break;
			}
		}
		
		if($html)
		{
			JHtml::_('behavior.framework');
			
			// Initialize JavaScript
			$dispatcher->trigger('onInit', $id);
		}
		
		return $html;
	}
	
	public function getCookieConsent()
	{
		$app = JFactory::getApplication();
		$cookieName = 'vpframework_cookie_consent_' . JUserHelper::getShortHashedUserAgent();
		$cookieName = JApplication::getHash($cookieName);
		
		if($app->input->cookie->get($cookieName))
		{
			return true;
		}
		
		return false;
	}
	
	public function setPageHeading($heading)
	{
		if(!empty($heading) && is_string($heading))
		{
			VPFrameworkGlobal::getInstance()->setState('page_title', (string) $heading);
		}
	}
	
	public function initialisePageHeadingInBreadcrumbs()
	{
		if($this->params->get('pagetitle_in_breadcrumbs') && JModuleHelper::isEnabled('breadcrumbs'))
		{
			$module = JModuleHelper::getModule('breadcrumbs');
			
			if(empty($module) || empty($module->position) || $module->position != 'breadcrumbs')
			{
				return false;
			}
			
			$app    = JFactory::getApplication();
			$params = $app->getParams();
			
			$show_page_heading = $params->get('show_page_heading');

			if(!empty($show_page_heading) || $show_page_heading === null)
			{
				if($heading = $params->get('page_heading'))
				{
					$this->setPageHeading($heading);
				}
				
				$option = strtolower($app->input->getCmd('option', ''));
				
				if($option && strpos($option, 'com_') === 0)
				{
					$cParams = $app->getParams($option);
					$cParams->set('show_page_heading', 0);
				}
				
				$params->set('show_page_heading', 0);
			}
		}
	}
	
	public function showPageHeadingInBreadcrumbs()
	{
		if($this->params->get('pagetitle_in_breadcrumbs') && JModuleHelper::isEnabled('breadcrumbs'))
		{
			$module = JModuleHelper::getModule('breadcrumbs');
			
			if(!empty($module) && !empty($module->position) && $module->position == 'breadcrumbs')
			{
				return true;
			}
		}
		
		return false;
	}
	
	public function getPageHeading($default = '')
	{
		$heading = VPFrameworkGlobal::getInstance()->getState('page_title', '');
		
		if(empty($heading))
		{
			$document = JFactory::getDocument();
			$heading  = $document->getTitle();
		}

		if(empty($heading))
		{
			$heading = $default;
		}
		
		$heading = !empty($heading) ? strip_tags($heading) : $heading;
		
		return (string) $heading;
	}
	
	public function getVersion()
	{
		$version = !empty($this->xml->version) ? (string) $this->xml->version : 'unknown';
		$version = !empty($version) ? $version : 'unknown';
		
		return $version;
	}
	
	public function getFrameworkVersion()
	{
		if($this->framework_xml === null)
		{
			$this->framework_xml = false;
			
			$manifest = JPath::clean(JPATH_SITE . '/plugins/system/vpframework/vpframework.xml');
			
			if(is_file($manifest))
			{
				$xml = JFactory::getXML($manifest);

				if(!empty($xml))
				{
					$this->framework_xml = $xml;
				}
			}
		}
		
		$version = !empty($this->framework_xml->version) ? (string) $this->framework_xml->version : 'unknown';
		$version = !empty($version) ? $version : 'unknown';

		return $version;
	}
	
	public function addStylesheet($filename, $version = null, $relative = true)
	{
		if(version_compare(JVERSION, '3.7.0', 'ge'))
		{
			$options = array();
			
			if($version)
			{
				$options['version'] = 'v=' . $version;
			}
			
			$options['relative'] = $relative;
			
			JHtml::_('stylesheet', $filename, $options);
		}
		else
		{
			JHtml::_('stylesheet', $filename, array(), true);
		}
	}
	
	public function addScript($filename, $version = null, $relative = true)
	{
		if(version_compare(JVERSION, '3.7.0', 'ge'))
		{
			$options = array();
			
			if($version)
			{
				$options['version'] = 'v=' . $version;
			}
			
			$options['relative'] = $relative;
			
			JHtml::_('script', $filename, $options);
		}
		else
		{
			JHtml::_('script', $filename, false, true);
		}
	}
}
