<?php
namespace JExtstore\Component\JRealtimeAnalytics\Administrator\Model;
/**
 *
 * @package JREALTIMEANALYTICS::CPANEL::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @author Joomla! Extensions Store
 * @copyright (C) 2013 - Joomla! Extensions Store
 * @license GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html 
 */
defined ( '_JEXEC' ) or die ( 'Restricted access' );
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Model as JRealtimeModel;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Exception as JRealtimeException;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Http;

define ('SERVER_REMOTE_URI', 'http://storejextensions.org/dmdocuments/updates/');
define ('UPDATES_FORMAT', '.json');

/**
 * CPanel model responsibilities contract
 *
 * @package JREALTIMEANALYTICS::CPANEL::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @since 1.0
 */
interface ICPanelModel {
	/**
	 * Get by remote server informations for new updates of this extension
	 *
	 * @access public
	 * @return mixed An object json decoded from server if update information retrieved correctly otherwise false
	 */
	public function getUpdates(Http $httpClient);
}
 
/**
 * CPanel model concrete implementation
 *
 * @package JREALTIMEANALYTICS::CPANEL::administrator::components::com_jrealtimeanalytics
 * @subpackage models
 * @since 1.0
 */
class CpanelModel extends JRealtimeModel implements ICPanelModel {
	/**
	 * Hold the start period by config
	 * 
	 * @access private
	 * @var string
	 */
	private $intervalFrom;
	
	/**
	 * Hold the end period by config
	 *
	 * @access private
	 * @var string
	 */
	private $intervalTo;
	
	/**
	 * Common WHERE period filter
	 *
	 * @access private
	 * @var string
	 */
	private $whereQuery;
	
	/**
	 * Total users by period
	 *
	 * @access protected
	 * @param string $field
	 * @param string $value
	 * @return string
	 */
	protected function buildListQueryTotalUsers() {
		$query = "SELECT COUNT(DISTINCT(" . $this->dbInstance->quoteName('session_id_person') . "))" .  
				 "\n FROM  #__realtimeanalytics_serverstats" .
				 $this->whereQuery;
		
		return $query;
	}
	
	/**
	 * Total pages by period
	 *
	 * @access protected
	 * @param string $field
	 * @param string $value
	 * @return string
	 */
	protected function buildListQueryTotalPages() {
		$query = "SELECT COUNT(*)" .  
				 "\n FROM  #__realtimeanalytics_serverstats" .
				 $this->whereQuery;
		return $query;
	}
	
	/**
	 * Total users registered to system
	 *
	 * @access protected
	 * @param string $field
	 * @param string $value
	 * @return string
	 */
	protected function buildListQuerySystemUsers() {
		$query = "SELECT COUNT(*) FROM #__users" .
	 	 		 "\n WHERE " . $this->dbInstance->quoteName('block') . " = 0";
		return $query;
	}
	
	/**
	 * Total active events
	 *
	 * @access protected
	 * @param string $field
	 * @param string $value
	 * @return string
	 */
	protected function buildListQuerySystemEvents() {
		$query = "SELECT COUNT(*) FROM #__realtimeanalytics_eventstats" .
	 	 		 "\n WHERE " . $this->dbInstance->quoteName('published') . " = 1";
		return $query;
	}
	
	/**
	 * Modules mobile list entities query
	 *
	 * @access protected
	 * @param string $field
	 * @param string $value
	 * @return string
	 */
	protected function buildListQueryStatsMap() {
		// Filter based on config settings period interval
		$fromPeriod = $this->getState('fromPeriod');
		$toPeriod = $this->getState('toPeriod');
		
		$whereQuery = "\n WHERE " .  $this->dbInstance->quoteName('visitdate') . " >= " . $this->dbInstance->quote($fromPeriod) .
					  "\n AND " .  $this->dbInstance->quoteName('visitdate') . " <= " . $this->dbInstance->quote($toPeriod);
		
		$query = "SELECT COUNT(DISTINCT(" . $this->dbInstance->quoteName('session_id_person') . ")) AS numusers," .  
				 $this->dbInstance->quoteName('geolocation') .
				 "\n FROM  #__realtimeanalytics_serverstats" .
				 $whereQuery .
				 "\n GROUP BY " . $this->dbInstance->quoteName('geolocation');
		
		return $query;
	}
	
	/**
	 * Main get data method
	 *
	 * @access public
	 * @return array
	 */
	public function getData(): array {
		// Store period nelle class properties, fixed not from userstate but only da config
		$this->intervalFrom = $this->getState('fromPeriod');
		$this->intervalTo = $this->getState('toPeriod');
		
		$this->whereQuery = "\n WHERE " .  $this->dbInstance->quoteName('visitdate') . " >= " . $this->dbInstance->quote($this->intervalFrom) .
							"\n AND " .  $this->dbInstance->quoteName('visitdate') . " <= " . $this->dbInstance->quote( $this->intervalTo );
		
		$calculatedStats = array();
		// Build queries
		try {
			// Total users visitors
			$query = $this->buildListQueryTotalUsers ();
			$this->dbInstance->setQuery ( $query );
			$calculatedStats ['chart_period_canvas'] ['totalusers'] = $this->dbInstance->loadResult ();
			// Total global modules
			
			// Total viewed pages
			$query = $this->buildListQueryTotalPages ();
			$this->dbInstance->setQuery ( $query );
			$calculatedStats ['chart_period_canvas'] ['totalpages'] = $this->dbInstance->loadResult ();
			// Total published modules
			
			// Total system users
			$query = $this->buildListQuerySystemUsers ();
			$this->dbInstance->setQuery ( $query );
			$calculatedStats ['chart_generic_canvas'] ['systemusers'] = $this->dbInstance->loadResult ();
			// Total published modules
			
			// Total system events
			$query = $this->buildListQuerySystemEvents ();
			$this->dbInstance->setQuery ( $query );
			$calculatedStats ['chart_generic_canvas'] ['systemevents'] = $this->dbInstance->loadResult ();
			// Total published modules
			
			// Data for geo map
			$query = $this->buildListQueryStatsMap ();
			$this->dbInstance->setQuery ( $query );
			$geolocationData = $this->dbInstance->loadAssocList ( 'geolocation' );
			// Total published modules

			// Normalize DB Data
			foreach ( $geolocationData as $country => $singleData ) {
				$calculatedStats ['geomap'] [strtolower ( $country )] = $singleData ['numusers'];
			}
		} catch ( JRealtimeException $e ) {
			$this->app->enqueueMessage ( $e->getMessage (), $e->getExceptionLevel () );
			$calculatedStats = array ();
		} catch ( \Exception $e ) {
			$jRealtimeException = new JRealtimeException ( $e->getMessage (), 'error' );
			$this->app->enqueueMessage ( $jRealtimeException->getMessage (), $jRealtimeException->getExceptionLevel () );
			$calculatedStats = array ();
		}
	
		return $calculatedStats;
	}
	
	/**
	 * Get by remote server informations for new updates of this extension
	 *
	 * @access public
	 * @return mixed An object json decoded from server if update information retrieved correctly otherwise false
	 */
	public function getUpdates(Http $httpClient) {
		// Updates server remote URI
		$option = $this->getState ( 'option', 'com_jrealtimeanalytics' );
		if (! $option) {
			return false;
		}
		$url = SERVER_REMOTE_URI . $option . UPDATES_FORMAT;
		
		// Try to get informations
		try {
			$response = $httpClient->get ( $url )->body;
			if ($response) {
				$decodedUpdateInfos = json_decode ( $response );
			}
			return $decodedUpdateInfos;
		} catch ( JRealtimeException $e ) {
			return false;
		} catch ( \Exception $e ) {
			return false;
		}
	}
}