<?php
/**
 * @package DJ-Catalog2
 * @copyright Copyright (C) DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 */
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
use Joomla\Utilities\ArrayHelper;
use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper;
use Joomla\Component\Actionlogs\Administrator\Plugin\ActionLogPlugin;

//JLoader::register('ActionLogPlugin', JPATH_ADMINISTRATOR . '/components/com_actionlogs/libraries/actionlogplugin.php');
//JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

defined('_JEXEC') or die;

class PlgActionlogDJCatalog2 extends ActionLogPlugin
{
	protected $contextAliases = array(
		// Back-end MVS structures
		'com_djcatalog2.cartfield' => 'com_djcatalog2.cartfield',
		'com_djcatalog2.category' => 'com_djcatalog2.category',
		'com_djcatalog2.country' => 'com_djcatalog2.country',
		'com_djcatalog2.coupon' => 'com_djcatalog2.coupon',
		'com_djcatalog2.customer' => 'com_djcatalog2.customer',
		'com_djcatalog2.customergroup' => 'com_djcatalog2.customergroup',
		'com_djcatalog2.customisation' => 'com_djcatalog2.customisation',
		'com_djcatalog2.delivery' => 'com_djcatalog2.delivery',
		'com_djcatalog2.field' => 'com_djcatalog2.field',
		'com_djcatalog2.fieldgroup' => 'com_djcatalog2.fieldgroup',
		'com_djcatalog2.import' => 'com_djcatalog2.import',
		'com_djcatalog2.importconfig' => 'com_djcatalog2.importconfig',
		'com_djcatalog2.item' => 'com_djcatalog2.item',
		'com_djcatalog2.label' => 'com_djcatalog2.label',
		'com_djcatalog2.order' => 'com_djcatalog2.order',
		'com_djcatalog2.orderstatus' => 'com_djcatalog2.orderstatus',
		'com_djcatalog2.payment' => 'com_djcatalog2.payment',
		'com_djcatalog2.pricerule' => 'com_djcatalog2.pricerule',
		'com_djcatalog2.prices' => 'com_djcatalog2.prices',
		'com_djcatalog2.producer' => 'com_djcatalog2.producer',
		'com_djcatalog2.producercategory' => 'com_djcatalog2.producercategory',
		'com_djcatalog2.producerfield' => 'com_djcatalog2.producerfield',
		'com_djcatalog2.query' => 'com_djcatalog2.query',
		'com_djcatalog2.state' => 'com_djcatalog2.state',
		'com_djcatalog2.subscription' => 'com_djcatalog2.subscription',
		'com_djcatalog2.taxrate' => 'com_djcatalog2.taxrate',
		'com_djcatalog2.taxrule' => 'com_djcatalog2.taxrule',
		'com_djcatalog2.thumbs' => 'com_djcatalog2.thumbs',
		'com_djcatalog2.unit' => 'com_djcatalog2.unit',
		'com_djcatalog2.userfield' => 'com_djcatalog2.userfield',
		'com_djcatalog2.vatrate' => 'com_djcatalog2.vatrate',
		'com_djcatalog2.vatrule' => 'com_djcatalog2.vatrule',
		'com_djcatalog2.vendor' => 'com_djcatalog2.vendor',
		
		// Front-end MVC structures
		'com_djcatalog2.address' => 'com_djcatalog2.address',
		'com_djcatalog2.itemform' => 'com_djcatalog2.item',
		'com_djcatalog2.myitems' => 'com_djcatalog2.item',
		//'com_djcatalog2.order' => 'com_djcatalog2.order',
		'com_djcatalog2.orderform' => 'com_djcatalog2.order',
		'com_djcatalog2.query' => 'com_djcatalog2.query',
		'com_djcatalog2.question' => 'com_djcatalog2.question',
		'com_djcatalog2.questionform' => 'com_djcatalog2.query',
		//'com_djcatalog2.wishes' => 'com_djcatalog2.wishes'
	);
	
	protected $customContexts = array(
		'items.set_prices' => 'items.set_prices',
		//'orders.change_status' => 'com_djcatalog2.order',
		'items.import' => 'com_djcatalog2.item',
		'items.import_prices' => 'com_djcatalog2.item',
		'categories.import' => 'com_djcatalog2.category',
		'producers.import' => 'com_djcatalog2.producer',
		'thumbs.go' => 'com_djcatalog2.thumbs.go',
		'thumbs.purge' => 'com_djcatalog2.thumbs.purge',
		'thumbs.resmushit' => 'com_djcatalog2.thumbs.resmushit',
		'wish.add' => 'com_djcatalog2.wish.add',
		'wish.remove' => 'com_djcatalog2.wish.remove'
	);
	
	public function onAfterRoute(){
		$option = $this->app->input->getCmd('option');
		if ($option != 'com_djcatalog2') return;
		
		
		$task = $this->app->input->getCmd('task');
		$context = 'com_djcatalog2.' . $task;
		
		if (empty($task) || !isset($this->customContexts[$task])) {
			return;
		}
		
		if ($this->validateSettings($task, 'custom_route') == false) {
			return;
		}
		
		$entryType = 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK_NAME_' . str_replace('.', '_', $task);
		
		$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK';
		$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK_' . str_replace('.', '_', $task);
		
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}
		
		if (!$this->app->getLanguage()->hasKey($entryType))
		{
			$entryType = $task;
		}
		
		$messages = ($this->app->isClient('administrator')) ? $this->getBackendCustomTaskMessage($task, $entryType) : $this->getFrontendCustomTaskMessage($task, $entryType);
		if (is_array($messages)) {
			$this->addLog($messages, $messageLanguageKey, $this->customContexts[$task]);
		}
			
	}
	
	public function onContentAfterSave($context, $data, $isNew)
	{
		if (!isset($this->contextAliases[$context])) {
			return;
		}
		
		$context = $this->contextAliases[$context];
		
		$ctxParts = explode('.', $context);
		$type = (isset($ctxParts[1])) ? $ctxParts[1] : false;
		
		if (!$type) return;
		
		if ($this->validateSettings($context, 'save') == false) {
			return;
		}
		
		if ($isNew)
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_ADDED';
			$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_ADDED';
		}
		else
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_UPDATED';
			$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_UPDATED';
		}
		
		// If the content type doesn't has it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}
		
		$entryType = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type;
		if (!$this->app->getLanguage()->hasKey($entryType))
		{
			$entryType = $type;
		}
		
		$option = $this->app->input->getCmd('option');
		$params = $this->getLinkVars($type);
		
		$pk = $params['pk'];
		$pkHolder = $params['pk_holder'];
		$entName = $params['ent_name'];
		
		$id = empty( $data->$pk) ? 0 : $data->$pk;
		
		$message = array(
			'action'   => $isNew ? 'add' : 'update',
			'type'     => $entryType,
			'id'       => $id,
			'title'    => $data->$entName,
		);
		
		if (empty($params['no_link'])) {
			$message['itemlink']  = ActionlogsHelper::getContentTypeLink($option, $type, $id, $pkHolder);
		}
		
		$this->addLog(array($message), $messageLanguageKey, $context);
	}
	
	public function onContentAfterDelete($context, $data)
	{
		if (!isset($this->contextAliases[$context])) {
			return;
		}
		
		$context = $this->contextAliases[$context];
		
		$ctxParts = explode('.', $context);
		$type = (isset($ctxParts[1])) ? $ctxParts[1] : false;
		
		if (!$type) return;
		
		if ($this->validateSettings($context, 'delete') == false) {
			return;
		}
		
		$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_DELETED';
		$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_DELETED';
		
		// If the content type doesn't has it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}
		
		$entryType = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type;
		if (!$this->app->getLanguage()->hasKey($entryType))
		{
			$entryType = $type;
		}
		
		$params = $this->getLinkVars($type);
		
		$pk = $params['pk'];
		$entName = $params['ent_name'];
		
		$id = empty( $data->$pk) ? 0 : $data->$pk;
		
		$message = array(
			'action'   => 'delete',
			'type'     => $entryType,
			'id'       => $id,
			'title'    => $data->$entName
		);
		
		$this->addLog(array($message), $messageLanguageKey, $context);
	}
	
	public function onContentChangeState($context, $pks, $value)
	{
		if (!isset($this->contextAliases[$context])) {
			return;
		}
		
		$context = $this->contextAliases[$context];
		
		$ctxParts = explode('.', $context);
		$type = (isset($ctxParts[1])) ? $ctxParts[1] : false;
		
		if (!$type) return;
		
		if ($this->validateSettings($context, 'change_state') == false) {
			return;
		}
		
		switch ($value)
		{
			case 0:
				$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_UNPUBLISHED';
				$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_UNPUBLISHED';
				$action             = 'unpublish';
				break;
			case 1:
				$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_PUBLISHED';
				$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_PUBLISHED';
				$action             = 'publish';
				break;
			case 2:
				$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_ARCHIVED';
				$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_ARCHIVED';
				$action             = 'archive';
				break;
			case -2:
				$messageLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type . '_TRASHED';
				$defaultLanguageKey = 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_TRASHED';
				$action             = 'trash';
				break;
			default:
				$messageLanguageKey = '';
				$defaultLanguageKey = '';
				$action             = '';
				break;
		}
		
		// If the content type doesn't has it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}
		
		$entryType = 'PLG_ACTIONLOG_DJCATALOG2_TYPE_' . $type;
		if (!$this->app->getLanguage()->hasKey($entryType))
		{
			$entryType = $type;
		}
		
		$option = $this->app->input->getCmd('option');
		$params = $this->getLinkVars($type);
		
		if (empty($params['table_name'])) {
			return; 
		}
		
		$pk = $params['pk'];
		$pkHolder = $params['pk_holder'];
		$entName = $params['ent_name'];
		
		$id = empty( $data->$pk) ? 0 : $data->$pk;
		
		$db    = $this->db;
		$query = $db->getQuery(true)
		->select($db->quoteName(array($entName, $pkHolder)))
		->from($db->quoteName($params['table_name']))
		->where($db->quoteName($pkHolder) . ' IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
		$db->setQuery($query);
		
		try
		{
			$items = $db->loadObjectList($pkHolder);
		}
		catch (RuntimeException $e)
		{
			$items = array();
		}
		
		$messages = array();
		
		foreach ($pks as $pk)
		{
			$message = array(
				'action'      => $action,
				'type'        => $entryType,
				'id'          => $pk,
				'title'       => $items[$pk]->$entName
			);
			
			if (empty($params['no_link'])) {
				$message['itemlink']  = ActionlogsHelper::getContentTypeLink($option, $type, $pk, $pkHolder);
			}
			
			$messages[] = $message;
		}
		
		$this->addLog($messages, $messageLanguageKey, $context);
	}
	
	public function onDJCatalog2ItemContactFormSubmit($data, $item) {
		if ($this->params->get('item_contact') == false) {
			return;
		}
		$message = array(
			'action'   => 'contact',
			'type'     => 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK_NAME_CONTACT',
			'id'       => $item->id,
			'title'    => $item->name,
			'itemlink' => ActionlogsHelper::getContentTypeLink('com_djcatalog2', 'item', $item->id, 'id'),
			'email' => $data['contact_email']
		);
		
		$this->addLog(array($message), 'PLG_ACTIONLOG_DJCATALOG2_CONTENT_ITEM_CONTACT', 'com_djcatalog2.item.contact');
	}
	
	public function onDJC2AfterOrderStatusChange($data) {
		if ($this->params->get('order_status') == false) {
			return;
		}
		$message = array(
			'action'      => 'update',
			'type'        => 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK_NAME_ORDERS_CHANGE_STATUS',
			'id'          => $data['id'],
			'title'       => $data['order_number'],
			'itemlink'    => ActionlogsHelper::getContentTypeLink('com_djcatalog2', 'order', $data['id'], 'id')
		);
		
		$this->addLog(array($message), 'PLG_ACTIONLOG_DJCATALOG2_CUSTOM_TASK_ORDERS_CHANGE_STATUS', 'com_djcatalog2.order');
	}
	
	protected function getLinkVars($type) {
		$pkHolder ='id';
		$pk = 'id';
		$entName = 'name';
		$tableName = '';
		$noLink = null;
		
		switch ($type) {
			case 'address' : {
				$tableName = '#__djc2_addresses';
				$noLink = true;
				break;
			}
			case 'cartfield' : {
				$tableName = '#__djc2_cart_extra_fields';
				break;
			}
			case 'category' : {
				$tableName = '#__djc2_categories';
				break;
			}
			case 'country' :{
				$tableName = '#__djc2_countries';
				$entName = 'country_name';
				break;
			}
			case 'coupon' : {
				$tableName = '#__djc2_coupons';
				$entName = 'code';
				break;
			}
			case 'customer' : {
				break;
			}
			case 'customergroup' : {
				$tableName = '#__djc2_customer_groups';
				break;
			}
			case 'customisation' : {
				$tableName = '#__djc2_customisations';
				break;
			}
			case 'delivery' : {
				$tableName = '#__djc2_delivery_methods';
				break;
			}
			case 'field' : {
				$tableName = '#__djc2_items_extra_fields';
				break;
			}
			case 'fieldgroup' : {
				$tableName = '#__djc2_items_extra_fields_groups';
				break;
			}
			case 'importconfig' : {
				$tableName = '#__djc2_import_configs';
				break;
			}
			case 'item' : {
				$tableName = '#__djc2_items';
				break;
			}
			case 'label' : {
				$tableName = '#__djc2_labels';
				break;
			}
			case 'order' :{
				$tableName = '#__djc2_orders';
				$entName = 'order_number';
				break;
			}
			case 'orderstatus' : {
				$tableName = '#__djc2_order_statuses';
				break;
			}
			case 'payment' : {
				$tableName = '#__djc2_payment_methods';
				break;
			}
			case 'pricerule' : {
				$tableName = '#__djc2_price_rules';
				break;
			}
			case 'producer' : {
				$tableName = '#__djc2_producers';
				break;
			}
			case 'producercategory' : {
				$tableName = '#__djc2_producer_categories';
				break;
			}
			case 'producerfield' : {
				$tableName = '#__djc2_producers_extra_fields';
				break;
			}
			case 'query' : {
				$entName = 'id';
				$tableName = '#__djc2_quotes';
				break;
			}
			case 'state' : {
				$tableName = '#__djc2_countries_states';
				break;
			}
			case 'subscription' : {
				$tableName = '#__djc2_subscriptions';
				$entName = 'item_name';
				break;
			}
			case 'unit' : {
				$tableName = '#__djc2_units';
				break;
			}
			case 'vatrate' : {
				$tableName = '#__djc2_vat_rates';
				break;
			}
			case 'vatrule' : {
				$tableName = '#__djc2_vat_rules';
				break;
			}
			case 'vendor' : {
				$tableName = '#__djc2_vendors';
				$entName = 'user_id';
				break;
			}
			default: {
				$entName = '';
				$pkHolder = null;
				$pk = 0;
				break;
			}
		}
		
		return ['pk' => $pk, 'pk_holder' => $pkHolder, 'ent_name' => $entName, 'table_name' => $tableName, 'no_link' => $noLink];
	}
	
	protected function getBackendCustomTaskMessage($task, $entryType) {
		$messages = array();
		
		if ($task == 'orders.change_status') {
			$oids = $this->app->input->get('cid', array(), 'array');
			$db    = $this->db;
			$query = $db->getQuery(true)
			->select($db->quoteName(array('order_number', 'id')))
			->from('#__djc2_orders')
			->where('id IN (' . implode(',', ArrayHelper::toInteger($oids)) . ')');
			$db->setQuery($query);
			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				$items = array();
			}
			
			foreach ($oids as $pk)
			{
				$message = array(
					'action'      => 'update',
					'type'        => $entryType,
					'id'          => $pk,
					'title'       => $items[$pk]->order_number,
					'itemlink'    => ActionlogsHelper::getContentTypeLink('com_djcatalog2', 'order', $pk, 'id')
				);
				
				$messages[] = $message;
			}
		} else {
			$messages[] = array(
				'action'   => 'task',
				'type'     => $entryType,
				'id'       => 0,
				'title'    => ''
			);
		}
		
		return $messages;
	}
	
	protected function canLogCustomBackendTask($task) {
		if ($task == 'thumbs.go') {
			if ($this->app->input->getInt('image_id', 0) > 0) {
				return false;
			}
		} else if ($task == 'thumbs.resmushit') {
			$alreadyLogged = $this->app->getUserState('plg_actionlog_djcatalog2.started.' . $task);
			if ($alreadyLogged) {
				return false;
			}
			$this->app->setUserState('plg_actionlog_djcatalog2.started.' . $task, 1);
		} else if ($task == 'orders.change_status') {
			return $this->params->get('order_status');
		}
		
		return true;
	}
	
	protected function getFrontendCustomTaskMessage($task, $entryType) {
		$messages = array();
		
		if ($task == 'wish.add' || $task == 'wish.remove') {
			$ids = $this->app->input->get('cid', array(), 'array');
			$id = $this->app->input->getInt('item_id');
			
			$pks = array();
			if (empty($ids) && $task == 'wish.remove' || empty($id) && $task =='wish.add') {
				return false;
			} else if ($task == 'wish.add') {
				$pks[] = $id;
			} else {
				$pks = $ids;
			}
			
			$db    = $this->db;
			$query = $db->getQuery(true)
			->select($db->quoteName(array('name', 'id')))
			->from('#__djc2_items')
			->where('id IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
			$db->setQuery($query);
			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				$items = array();
			}
			
			foreach ($pks as $pk)
			{
				$message = array(
					'action'      => $task == 'wish.remove' ? 'delete' : 'add',
					'type'        => $entryType,
					'id'          => $pk,
					'title'       => $items[$pk]->name,
					'itemlink'    => ActionlogsHelper::getContentTypeLink('com_djcatalog2', 'item', $pk, 'id')
				);
				
				$messages[] = $message;
			}
		} else {
			$messages[] = array(
				'action'   => 'task',
				'type'     => $entryType,
				'id'       => 0,
				'title'    => ''
			);
		}
		
		return $messages;
	}
	
	protected function canLogCustomFrontendTask($task) {
		if ($task == 'orders.change_status') {
			return $this->params->get('order_status') ? true : false;
		}
		return true;
	}
	
	protected function validateSettings($context, $area) {
		switch ($area) {
			case 'save' : {
				// Exception
				if ($context == 'com_djcatalog2.order') {
					return $this->params->get('order_status');
				}
				if ($this->app->isClient('administrator')) {
					return $this->params->get('core_content_update');
				} else {
					return $this->params->get('core_front_content_update');
				}
				break;
			}
			case 'delete' : {
				if ($this->app->isClient('administrator')) {
					return $this->params->get('core_content_update');
				} else {
					return $this->params->get('core_front_content_update');
				}
				break;
			}
			case 'change_state' : {
				if ($this->app->isClient('administrator')) {
					return $this->params->get('core_content_state_update');
				} else {
					return $this->params->get('core_front_content_state_update');
				}
				break;
			}
			case 'custom_route' : {
				if ($this->app->isClient('administrator')) {
					return $this->canLogCustomBackendTask($context);
				} else {
					return $this->canLogCustomFrontendTask($context);
				}
				break;
			}
		}
		
		return true;
	}
}