<?php
/**
 * @package    Essentials for VirtueMart
 * @author     Abhishek Das <info@virtueplanet.com>
 * @copyright  Copyright (C) 2012-2024 VirtuePlanet Services LLP. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       https://www.virtueplanet.com
 */

defined('_JEXEC') or die;

use \Joomla\CMS\Factory;

jimport('joomla.application.component.modellist');

// Register utility helper
JLoader::register('VMEssentialsHelperUtility', VMESSENTIALS_SITE . '/helpers/utility.php');

/**
 * Methods supporting a list of Wishlist records.
 *
 * @since  1.6
 */
class VMEssentialsModelWishlist extends JModelList
{
	protected $cookieName = '_vmessentials_wishlist';
	
	/**
	 * Method to auto-populate the state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the
	 * configuration flag to ignore the request is set.
	 *
	 * @return  void
	 *
	 * @note    Calling getState in this method will result in recursion.
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$input = Factory::getApplication()->input;
		
		$id = $input->getCmd('id', '');
		$this->setState('id', $id);
		
		parent::populateState($ordering, $direction);
	}
	
	protected function getStoreId($id = '')
	{
		// Add the list state to the store id.
		$id .= ':' . Factory::getUser()->get('id');
		$id .= ':' . $this->getState('list.start');
		$id .= ':' . $this->getState('list.limit');

		return md5($this->context . ':' . $id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return   JDatabaseQuery
	 *
	 * @since    1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$user  = Factory::getUser();
		$id    = $this->getState('id', '');

		// Select the required fields from the table.
		$query->select($db->quoteName('virtuemart_product_id'))
			->from($db->quoteName('#__vmessentials_wishlist'));
			
		if (!empty($id))
		{
			$userId = VMEssentialsHelperUtility::decode($id, true);
			$userId = $userId ? (int) $userId : 0;
			
			$query->where($db->quoteName('user_id'). ' = ' . (int) $userId);
		}
		else
		{
			$query->where($db->quoteName('user_id'). ' = ' . (int) $user->get('id'));
		}

		return $query;
	}
	
	public function getTable($type = 'Wishlist', $prefix = 'VMEssentialsTable', $config = array())
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_vmessentials/tables');
		
		return JTable::getInstance($type, $prefix, $config);
	}
	
	public function add($virtuemart_product_id)
	{
		$virtuemart_product_id = (int) $virtuemart_product_id;
		
		if (!is_numeric($virtuemart_product_id) || $virtuemart_product_id <= 0)
		{
			$this->setError(JText::_('COM_VMESSENTIALS_ERROR_INVALID_PRODUCT_ID'));
			return false;
		}
		
		$app    = Factory::getApplication();
		$user   = Factory::getUser();
		$params = $app->getParams('com_vmessentials');
		$items  = (array) $this->getAllItemIds();
		$items  = VMEssentialsHelpersVMEssentials::validateProductIds($items);
		
		if (!empty($items))
		{
			if (in_array($virtuemart_product_id, $items))
			{
				// Item exists in wishlist
				return true;
			}
			
			if (count($items) >= $params->get('wishlist_max_items', 999))
			{
				$this->setError(JText::_('COM_VMESSENTIALS_ERROR_MAX_LIMIT'));
				return false;
			}
		}

		if (!$user->get('guest'))
		{
			$table = $this->getTable();
			$data  = array('virtuemart_product_id' => (int) $virtuemart_product_id, 'user_id' => (int) $user->get('id'), 'state' => 1);
			
			try
			{
				// Bind the data.
				if (!$table->bind($data))
				{
					$this->setError($table->getError());
					return false;
				}
				
				// Check the data.
				if (!$table->check())
				{
					$this->setError($table->getError());
					return false;
				}
				
				// Store the data.
				if (!$table->store())
				{
					$this->setError($table->getError());
					return false;
				}
			}
			catch(Exception $e)
			{
				$this->setError($e->getMessage());
				return false;
			}
		}
		else
		{
			$session = Factory::getSession();
			$items[] = $virtuemart_product_id;
			
			$session->set('wishlist', $items, 'vmessentials');
			
			if ($params->get('use_cookie', 1))
			{
				$this->saveItemsToCookie($items);
			}
		}
		
		$this->cleanCache();
		
		return true;
	}
	
	public function remove($virtuemart_product_id)
	{
		$virtuemart_product_id = (int) $virtuemart_product_id;
		
		if (!is_numeric($virtuemart_product_id) || $virtuemart_product_id <= 0)
		{
			$this->setError(JText::_('COM_VMESSENTIALS_ERROR_INVALID_PRODUCT_ID'));
			return false;
		}
		
		$app    = Factory::getApplication();
		$user   = Factory::getUser();
		$params = $app->getParams('com_vmessentials');
		$items  = (array) $this->getAllItemIds();

		if (empty($items) || !in_array($virtuemart_product_id, $items))
		{
			// Item does not exists in the wishlist
			$this->setError(JText::_('COM_VMESSENTIALS_ERROR_INVALID_PRODUCT_ID'));
			return true;
		}

		if (!$user->get('guest'))
		{
			try
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true);
				
				$conditions = array(
					$db->quoteName('user_id') . ' = ' . (int) $user->get('id'), 
					$db->quoteName('virtuemart_product_id') . ' = ' . (int) $virtuemart_product_id
				);
				 
				$query->delete($db->quoteName('#__vmessentials_wishlist'));
				$query->where($conditions);
				
				$db->setQuery($query);
				$db->execute();
			}
			catch(Exception $e)
			{
				$this->setError($e->getMessage());
				return false;
			}
		}
		else
		{
			$session = Factory::getSession();
			$key = array_search($virtuemart_product_id, $items);
			
			if ($key !== false)
			{
				unset($items[$key]);
				
				$session->set('wishlist', $items, 'vmessentials');
				
				if ($params->get('use_cookie', 1))
				{
					$this->saveItemsToCookie($items);
				}
			}
		}
		
		$this->cleanCache();
		
		return true;
	}
	
	public function getAllItemIds()
	{
		// Get a storage key.
		$store = $this->getStoreId('allItems');
		
		// Try to load the data from internal storage.
		if (isset($this->cache[$store]))
		{
			return $this->cache[$store];
		}
		
		$user = Factory::getUser();
		$id   = $this->getState('id', '');
		
		if (!$user->get('guest') || !empty($id))
		{
			try
			{
				$db = $this->getDbo();
				$db->setQuery($this->_getListQuery());

				$this->cache[$store] = $db->loadColumn();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());
				return false;
			}
		}
		else
		{
			$allItems            = $this->getGuestItems();
			$this->cache[$store] = is_array($allItems) && !empty($allItems) ? $allItems : array();
		}
		
		$this->cache[$store] = !empty($this->cache[$store]) ? array_map('intval', $this->cache[$store]) : $this->cache[$store];
		
		return $this->cache[$store];
	}

	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId();
		
		// Try to load the data from internal storage.
		if (isset($this->cache[$store]))
		{
			return $this->cache[$store];
		}
		
		$user = Factory::getUser();
		$id   = $this->getState('id', '');
		
		if (!$user->get('guest') || !empty($id))
		{
			try
			{
				$db = $this->getDbo();
				$db->setQuery($this->_getListQuery(), $this->getStart(), $this->getState('list.limit'));

				$virtuemart_product_ids = $db->loadColumn();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());
				return false;
			}
		}
		else
		{
			$allItems = $this->getGuestItems();
			$start    = $this->getStart();
			$limit    = $this->getState('list.limit');

			$virtuemart_product_ids = is_array($allItems) && !empty($allItems) ? array_slice($allItems, $start, $limit) : array();
		}
		
		$virtuemart_product_ids = VMEssentialsHelpersVMEssentials::validateProductIds($virtuemart_product_ids);

		if (is_array($virtuemart_product_ids) && !empty($virtuemart_product_ids))
		{
			$model       = VmModel::getModel('Product');
			$ratingModel = VmModel::getModel('ratings');

			$model->withRating = $ratingModel->showRating();

			$products = $model->getProducts($virtuemart_product_ids);

			$model->addImages($products, 1);

			if (!empty($products))
			{
				JLoader::register('vmCustomPlugin', JPATH_VM_PLUGINS . '/vmcustomplugin.php');
				
				$customfieldsModel = VmModel::getModel('Customfields');

				foreach ($products as $key => $productItem)
				{
					if (!empty($productItem->customfields))
					{
						$product = clone($productItem);
						$customfields = array();
						
						foreach ($productItem->customfields as $cu)
						{
							$customfields[] = clone($cu);
						}

						$customfieldsSorted = array();
						$customfieldsModel->displayProductCustomfieldFE($product, $customfields);
						//$product->stock = self::getStockText($productItem);
						
						foreach ($customfields as $k => $custom)
						{
							if (!empty($custom->layout_pos))
							{
								$customfieldsSorted[$custom->layout_pos][] = $custom;
								unset($customfields[$k]);
							}
						}
						
						$customfieldsSorted['normal'] = $customfields;
						$product->customfieldsSorted  = $customfieldsSorted;

						unset($product->customfields);

						$products[$key] = $product;
					} 
					else
					{
						$products[$key] = $productItem;
					}
				}
			}
			
			$this->cache[$store] = $products;
		}
		else
		{
			$this->cache[$store] = array();
		}
		
		return $this->cache[$store];
	}

	protected function _getListCount($query)
	{
		$user = Factory::getUser();
		
		if (!$user->get('guest'))
		{
			$count = parent::_getListCount($query);
		}
		else
		{
			$items = $this->getGuestItems();
			$count = is_array($items) ? count($items) : 0;
		}
		
		return $count;
	}
	
	public function getGuestItems($force = false)
	{
		// Get a storage key.
		$store = $this->getStoreId('guestItems');

		if (!isset($this->cache[$store]) || $force)
		{
			$app     = Factory::getApplication();
			$params  = $app->getParams('com_vmessentials');
			$session = Factory::getSession();
			$items   = array();
			
			if ($params->get('use_cookie', 1))
			{
				$items = $this->getItemsFromCookie();
			}
			
			$this->cache[$store] = (array) $session->get('wishlist', $items, 'vmessentials');
		}
		
		return $this->cache[$store];
	}

	protected function getItemsFromCookie($force = false)
	{
		// Get a storage key.
		$store = $this->getStoreId('cookieItems');
		
		if (!isset($this->cache[$store]) || $force)
		{
			$app    = Factory::getApplication();
			$filter = JFilterInput::getInstance();
			$items  = array();
			
			if ($str = $app->input->cookie->get($this->cookieName, '', 'raw'))
			{
				$cookieData = @unserialize(VMEssentialsHelperUtility::decode($str));
				
				if ($cookieData && is_array($cookieData))
				{
					foreach ($cookieData as $item)
					{
						$item = (int) $filter->clean($item);
						
						if ($item > 0)
						{
							$items[] = $item;
						}
					}
				}
			}
			
			//vp_dump($items);exit;
			
			$this->cache[$store] = $items;
		}
		
		return $this->cache[$store];
	}
	
	public function clearGuestList()
	{
		$session = Factory::getSession();
		$app     = Factory::getApplication();
		$params  = $app->getParams('com_vmessentials');
		$items   = array();

		$session->set('wishlist', $items, 'vmessentials');
		
		if ($params->get('use_cookie', 1))
		{
			$this->saveItemsToCookie($items);
		}
	}
	
	public function getPermalink()
	{
		$user = Factory::getUser();
		
		if ($user->get('guest'))
		{
			return false;
		}
		
		$userId   = (int) $user->get('id');
		$publicId = VMEssentialsHelperUtility::encode($userId);
		$pageUrl  = VMEssentialsHelperRoute::getRoute('wishlist') . '&id=' . $publicId;
		
		return $pageUrl;
	}
	
	public function resetCache()
	{
		$this->cache = array();
		
		$this->cleanCache();
	}
	
	protected function saveItemsToCookie($items)
	{
		$app          = Factory::getApplication();
		$params       = $app->getParams('com_vmessentials');
		$config       = Factory::getConfig();
		$cookieDomain = $config->get('cookie_domain', '');
		$cookiePath   = $config->get('cookie_path', '/');
		$lifetime     = 60 * 60 * 24 * (int) $params->get('cookie_lifetime', 30); // cookie_lifetime is days. Life time in seconds.
		
		$app->input->cookie->set($this->cookieName, VMEssentialsHelperUtility::encode(serialize($items)), (time() + $lifetime), $cookiePath, $cookieDomain, $app->isHttpsForced(), true);
	}
}
