<?php
namespace JExtstore\Component\JRealtimeAnalytics\Administrator\Model;
/**
 *
 * @package JREALTIMEANALYTICS::EVENTSTATS::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @author Joomla! Extensions Store
 * @copyright (C) 2014 - Joomla! Extensions Store
 * @license GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html
 */
defined ( '_JEXEC' ) or die ( 'Restricted access' );
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Model as JRealtimeModel;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Exception as JRealtimeException;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Html\Categories as JRealtimeHtmlCategories;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Html\Extensions as JRealtimeHtmlExtensions;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Html\Menu as JRealtimeHtmlMenu;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Helpers\Html as JRealtimeHelpersHtml;
/**
 * Sources model responsibilities
 *
 * @package JREALTIMEANALYTICS::EVENTSTATS::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @since 1.0
 */
interface IEventstatsModel {
	/**
	 * Return a list of subrecords for event details report
	 * 
	 * @access public
	 * @param int
	 * @return array
	 */
	public function getEventDetails($eventID);
}

/**
 * Sources model concrete implementation <<testable_behavior>>
 *
 * @package JREALTIMEANALYTICS::EVENTSTATS::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @since 1.0
 */
class EventstatsModel extends JRealtimeModel implements IEventstatsModel {
	/**
	 * Records query result set
	 *
	 * @access private
	 * @var Object[]
	 */
	private $records;
	
	/**
	 * Build list entities query
	 *
	 * @access protected
	 * @return string
	 */
	protected function buildListQuery() {
		// WHERE
		$where = array ();
		$order = array();
		$whereString = null;
		$orderString = null;
		// STATE FILTER
		if ($filter_state = $this->state->get ( 'state' )) {
			if ($filter_state == 'P') {
				$where [] = 's.published = 1';
			} else if ($filter_state == 'U') {
				$where [] = 's.published = 0';
			}
		}
		
		// PERIOD FILTER
		if($this->getState('fromPeriod')) {
			$where [] = $this->dbInstance->quoteName('t.eventdate') . " >= " . $this->dbInstance->quote($this->getState('fromPeriod'));
		}
		if($this->getState('toPeriod')) {
			$where [] = $this->dbInstance->quoteName('t.eventdate') . " <= " . $this->dbInstance->quote($this->getState('toPeriod'));
		}
		
		// TYPE FILTER
		if ($this->state->get ( 'type' )) {
			$where [] = "s.type = " . $this->dbInstance->quote ( $this->state->get ( 'type' ) );
		}
		
		// CATID FILTER
		if ($this->state->get ( 'catid' )) {
			$where [] = "s.catid = " . $this->dbInstance->quote ( $this->state->get ( 'catid' ) );
		}
		
		// TEXT FILTER
		if ($this->state->get ( 'searchword' )) {
			$where [] = "s.name LIKE " . $this->dbInstance->quote("%" . $this->state->get ( 'searchword' ) . "%");
		}
		
		if (count ( $where )) {
			$whereString = "\n WHERE " . implode ( "\n AND ", $where );
		}
		
		// ORDERBY
		if($this->state->get ( 'order' ) == 's.ordering' ) {
			$order[] = 'cat.title ';
		}
		
		if ($this->state->get ( 'order' )) {
			$order[] = $this->state->get ( 'order' );
		}
		
		if(count($order)) {
			$orderString = "\n ORDER BY " . implode ( ", ", $order );
		}
		
		// ORDERDIR
		if ($this->state->get ( 'order_dir' )) {
			$orderString .= " " . $this->state->get ( 'order_dir' );
		}
		
		$query = "SELECT s.*, u.name AS editor, cat.title AS cat_title," .
				 "\n COUNT(t.event_id) AS event_occurrences" . 
				 "\n FROM #__realtimeanalytics_eventstats AS s" . 
				 "\n LEFT JOIN #__realtimeanalytics_eventstats_track AS t" .
				 "\n ON t.event_id = s.id AND t.session_id IN (SELECT session_id_person FROM #__realtimeanalytics_serverstats)" .
				 "\n LEFT JOIN #__realtimeanalytics_categories AS cat" .
				 "\n ON cat.id = s.catid AND cat.id != 1" .
				 "\n LEFT JOIN #__users AS u" . 
				 "\n ON s.checked_out = u.id" . 
				 $whereString . 
				 "\n GROUP BY s.id" .
				 $orderString;
		return $query;
	}
	
	/**
	 * Storing entity by ORM table
	 *
	 * @access public
	 * @param bool $updateNulls
	 * @return mixed
	 */
	public function storeEntity($updateNulls = true) {
		return parent::storeEntity($updateNulls);
	}
	
	/**
	 * Load entity from ORM table
	 *
	 * @param array $ids        	
	 * @access public
	 * @return bool
	 */
	public function resetEntity($ids): bool {
		// Ciclo su ogni entity da cancellare
		if (is_array ( $ids ) && count ( $ids )) {
			foreach ( $ids as $id ) {
				try {
					$query = "DELETE FROM #__realtimeanalytics_eventstats_track" . 
							 "\n WHERE " . $this->dbInstance->quoteName('event_id') . ' = ' . $id;
					$this->dbInstance->setQuery($query);
					$this->dbInstance->execute();
				} catch (JRealtimeException $e) {
					$this->setException($e);
					return false;
				} catch (\Exception $e) {
					$jRealtimeException = new JRealtimeException($e->getMessage(), 'error');
					$this->setException($jRealtimeException);
					return false;
				}
			}
		}
		
		return true;
	}
	
	/**
	 * Return select lists used as filter for listEntities
	 *
	 * @access public
	 * @return array
	 */
	public function getFilters(): array {
		$filters = [];
		$filters ['state'] = JRealtimeHelpersHtml::state( $this->getState ( 'state' ) );
		
		$datasourceTypes = [];
		$datasourceTypes [] = HTMLHelper::_ ( 'select.option', null, Text::_ ( 'COM_JREALTIME' ) );
		$datasourceTypes [] = HTMLHelper::_ ( 'select.option', 'user', Text::_ ( 'COM_JREALTIME' ) );
		$datasourceTypes [] = HTMLHelper::_ ( 'select.option', 'menu', Text::_ ( 'COM_JREALTIME' ) );
		$datasourceTypes [] = HTMLHelper::_ ( 'select.option', 'content', Text::_ ( 'COM_JREALTIME' ) );
		$filters ['type'] = HTMLHelper::_ ( 'select.genericlist', $datasourceTypes, 'filter_type', 'onchange="Joomla.submitform();"', 'value', 'text', $this->getState ( 'type' ) );
		
		$categories = JRealtimeHtmlCategories::getOptions(true);
		$filters['categories'] = HTMLHelper::_('select.genericlist', $categories, 'filter_catid', 'class="inputbox" onchange=document.adminForm.submit();', 'value', 'text', $this->getState ( 'catid' ));
		
		return $filters;
	}
	
	/**
	 * Return select lists used as filter for editEntity
	 *
	 * @access public
	 * @param Object $record        	
	 * @return array
	 */
	public function getLists($record = null): array {
		$lists = [];
		// Grid states
		$lists ['published'] = JRealtimeHelpersHtml::booleanlist( 'published', null, $record->published );
		
		// Goal states
		$lists ['hasgoal'] = JRealtimeHelpersHtml::booleanlist( 'hasgoal', null, $record->hasgoal );
		
		// Notification states
		$notificationTypes = [];
		$notificationTypes [] = HTMLHelper::_ ( 'select.option', '0', Text::_ ( 'JNO' ) );
		$notificationTypes [] = HTMLHelper::_ ( 'select.option', '1', Text::_ ( 'COM_JREALTIME_EVENT_INCREMENT' ) );
		$notificationTypes [] = HTMLHelper::_ ( 'select.option', '2', Text::_ ( 'COM_JREALTIME_EVENT_GOAL_REACHED' ) );
		$lists ['hasgoalnotification'] = JRealtimeHelpersHtml::radiolist( $notificationTypes, 'goal_notification', 'class="form-select"', 'value', 'text', $record->goal_notification );
		
		$eventTypes = [];
		$eventTypes [] = HTMLHelper::_ ( 'select.option', null, Text::_ ( 'COM_JREALTIME_SELECT_EVENT_TYPE' ) );
		$eventTypes [] = HTMLHelper::_ ( 'select.option', 'viewurl', Text::_ ( 'COM_JREALTIME_VIEWURL' ) );
		$eventTypes [] = HTMLHelper::_ ( 'select.option', 'minpages', Text::_ ( 'COM_JREALTIME_MINPAGES' ) );
		$eventTypes [] = HTMLHelper::_ ( 'select.option', 'mintime', Text::_ ( 'COM_JREALTIME_MINTIME' ) );
		$eventTypes [] = HTMLHelper::_ ( 'select.option', 'mintimeonpage', Text::_ ( 'COM_JREALTIME_MINTIMEONPAGE' ) );
		$lists ['type'] = HTMLHelper::_ ( 'select.genericlist', $eventTypes, 'type', 'data-validation="required" aria-required="true" class="inputbox form-select"', 'value', 'text', $record->type );

		$menuOptions = JRealtimeHtmlMenu::getOptions();
		$lists['menupage']	= HTMLHelper::_('select.genericlist', $menuOptions, 'params[menupage]', 'class="inputbox form-select" data-switcher="1"', 'value', 'text', $record->params->get('menupage', null), 'menupage' );
		
		$trackMode = [
				HTMLHelper::_('select.option',  'menupage', Text::_( 'COM_JREALTIME_MENU_PAGE_TRACK' ) ),
				HTMLHelper::_('select.option',  'urlpage', Text::_( 'COM_JREALTIME_URL_PAGE_TRACK' ) )
		];
		$lists ['viewtype'] = JRealtimeHelpersHtml::radiolist( $trackMode, 'params[viewtype]', '', 'value', 'text', $record->params->get('viewtype', 'menupage'), 'params_viewtype_');
		
		$categories = JRealtimeHtmlCategories::getOptions();
		$lists['categories'] = HTMLHelper::_('select.genericlist', $categories, 'catid', 'class="inputbox form-select"', 'value', 'text', $record->catid);
		
		$extensions = JRealtimeHtmlExtensions::getOptions();
		$lists['extensions'] = HTMLHelper::_('select.genericlist', $extensions, 'params[extensions]', 'class="inputbox form-select"', 'value', 'text', $record->params->get('extensions', 0), 'params_extemsions_');
		
		return $lists;
	}
	
	/**
	 * Return a list of subrecords for event details report
	 *
	 * @access public
	 * @param int
	 * @return array
	 */
	public function getEventDetails($eventID) {
		$query = "SELECT track.*, stats.customer_name, stats.geolocation, stats.ip, stats.browser, stats.os" .
				 "\n FROM " . $this->dbInstance->quoteName('#__realtimeanalytics_eventstats_track') . " AS track" .
				 "\n INNER JOIN " . $this->dbInstance->quoteName( '#__realtimeanalytics_serverstats') . " AS stats" .
				 "\n ON track.session_id = stats.session_id_person" .
				 "\n WHERE " . $this->dbInstance->quoteName('event_id') . " = " . (int)($eventID) .
				 "\n GROUP BY " . $this->dbInstance->quoteName('event_id') . "," .
								  $this->dbInstance->quoteName('session_id') . "," .
								  $this->dbInstance->quoteName('eventdate') .
				 "\n ORDER BY " . $this->dbInstance->quoteName('eventdate') . " DESC";
		
		try {
			$this->dbInstance->setQuery ( $query );
			$result = $this->dbInstance->loadObjectList ();
		} catch ( JRealtimeException $e ) {
			$this->app->enqueueMessage ( $e->getMessage (), $e->getExceptionLevel () );
			$result = array ();
		} catch ( \Exception $e ) {
			$jRealtimeException = new JRealtimeException ( $e->getMessage (), 'error' );
			$this->app->enqueueMessage ( $jRealtimeException->getMessage (), $jRealtimeException->getExceptionLevel () );
			$result = array ();
		}
		return $result;
	}
}