<?php
namespace JExtstore\Component\JRealtimeAnalytics\Administrator\Controller;
/**
 *
 * @package JREALTIMEANALYTICS::SERVERSTATS::administrator::components::com_jrealtimeanalytics
 * @subpackage controllers
 * @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 Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Component\ComponentHelper;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Controller as JRealtimeController;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Graph\Generators\Charts as GraphGeneratorsCharts;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Renderers\Adapter\Pdf as RenderersAdapterPdf;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Renderers\Adapter\Csv as RenderersAdapterCsv;
use JExtstore\Component\JRealtimeAnalytics\Administrator\Framework\Renderers\Adapter\Xls as RenderersAdapterXls;

/**
 * Concrete class serverstats controller
 *
 * @package JREALTIMEANALYTICS::SERVERSTATS::administrator::components::com_jrealtimeanalytics
 * @subpackage controllers
 * @since 1.0
 */
class ServerstatsController extends JRealtimeController {
	/**
	 * Setta il model state a partire dallo userstate di sessione
	 * 
	 * @access protected
	 * @return object
	 */
	protected function setModelState($scope = 'default', $ordering = true): object {
		$option = $this->option;
		
		// Filtro Data DA... Data A... - Valori di default
		// Filter by current month - week - day
		$cParams = ComponentHelper::getParams ( $option );
		if ($cParams->get ( 'default_period_interval', 'week' ) == 'day') {
			$startPeriod = date ( "Y-m-d" );
			$endPeriod = date ( "Y-m-d" );
			
			// Optional override if the datetime is chosen for a single day
			if($cParams->get('stats_calendar_type', 'date') == 'datetime') {
				$endPeriod = date ( "Y-m-d", strtotime ( "+1 day", strtotime ( date ( "Y-m-d" ) ) ) );
			}
		} elseif ($cParams->get ( 'default_period_interval', 'week' ) == 'week') {
			$dt = time ();
			$startPeriod = date ( 'N', $dt ) == 1 ? date ( 'Y-m-d', $dt ) : date ( 'Y-m-d', strtotime ( 'last monday', $dt ) );
			$endPeriod = date ( 'N', $dt ) == 7 ? date ( 'Y-m-d', $dt ) : date ( 'Y-m-d', strtotime ( 'next sunday', $dt ) );
		} elseif ($cParams->get ( 'default_period_interval', 'week' ) == 'month') {
			$startPeriod = date ( "Y-m-01", strtotime ( date ( "Y-m-d" ) ) );
			$endPeriod = date ( "Y-m-d", strtotime ( "-1 day", strtotime ( "+1 month", strtotime ( date ( "Y-m-01" ) ) ) ) );
		}
		
		$fromPeriod = $this->getUserStateFromRequest ( "$option.$scope.fromperiod", 'fromperiod', strval ( $startPeriod ) );
		$toPeriod = $this->getUserStateFromRequest ( "$option.$scope.toperiod", 'toperiod', strval ( $endPeriod ) );

		// Get default model
		$defaultModel = parent::setModelState ( 'serverstats' );
		
		$defaultModel->setState('fromPeriodOriginal', $fromPeriod);
		$defaultModel->setState('toPeriodOriginal', $toPeriod);
		
		// Optional override if the datetime is chosen
		if($cParams->get('stats_calendar_type', 'date') == 'datetime') {
			$jConfig = Factory::getApplication()->getConfig();
			$joomlaConfigOffset = $jConfig->get('offset');
			$fromPeriodOffset = new \DateTime($fromPeriod, new \DateTimeZone($joomlaConfigOffset));
			$fromPeriodOffset->setTimezone(new \DateTimeZone("UTC"));
			$fromPeriod = $fromPeriodOffset->format("Y-m-d H:i:s");
			
			$toPeriodOffset = new \DateTime($toPeriod, new \DateTimeZone($joomlaConfigOffset));
			$toPeriodOffset->setTimezone(new \DateTimeZone("UTC"));
			$toPeriod = $toPeriodOffset->format("Y-m-d H:i:s");
		}
		
		$graphTheme = $this->getUserStateFromRequest ( "$option.$scope.graphtheme", 'graphtheme', 'Universal' );
		$statsReport = $this->getUserStateFromRequest ( "$option.$scope.statsreport", 'statsreport', 'full' );
		
		// Set model state
		$defaultModel->setState ( 'fromPeriod', $fromPeriod );
		$defaultModel->setState ( 'toPeriod', $toPeriod );
		$defaultModel->setState ( 'graphTheme', $graphTheme );
		$defaultModel->setState ( 'statsReport', $statsReport );
		$defaultModel->setState ( 'task', $this->task );
		
		return $defaultModel;
	}
	
	/**
	 * Default show stats
	 *
	 * @access public
	 * @return void
	 */
	public function display($cachable = false, $urlparams = false) {
		// Set model state
		$model = $this->setModelState ( 'serverstats' );
		
		// Graph Generators interface as Setter Dependency Injection
		$graphGenerator = new GraphGeneratorsCharts ( $model->getState ( 'graphTheme' ) );
		$model->setGraphRenderer ( $graphGenerator );
		
		// Get view always HTML format
		$view = $this->getView ('serverstats', 'html', '', array('base_path' => $this->basePath, 'layout' => 'default'));
		// Push the model into the view (as default)
		$view->setModel ( $model, true );
		
		// Call main template
		$prefixPath = null;
		if ($this->task === 'displaypdf') {
			$prefixPath = 'pdf_';
		}
		if ($this->task === 'displaycsv') {
			$prefixPath = 'csv_';
		}
		if ($this->task == 'displayxls') {
			$prefixPath = 'xls_';
		}
		$view->setLayout ( $prefixPath . 'graph' );
		
		// Creazione buffer output
		ob_start ();
		// Parent construction and view display
		$view->display ( 'main' );
		$bufferContent = ob_get_contents ();
		ob_end_clean ();
		
		// Choose if plain HTML or PDF conversion is required based on tasks instead of document format
		switch ($this->task) {
			case 'displaypdf' :
				// Do conversion to PDF format using adapter
				$pdfRenderer = new RenderersAdapterPdf ();
				$pdfRenderer->renderContent ( $bufferContent, $model, 'global_stats_report_' );
				break;
			case 'displaycsv' :
				$csvRenderer = new RenderersAdapterCsv ();
				$csvRenderer->renderContent ( $bufferContent, $model );
				break;
			case 'displayxls' :
				$xlsRenderer = new RenderersAdapterXls ();
				$xlsRenderer->renderContent ( $bufferContent, $model );
				break;
			default :
				echo $bufferContent;
		}
	}
	
	/**
	 * Manual AI analysis trigger from toolbar.
	 *
	 * @access public
	 * @return void
	 */
	public function runaianalysis() {
		$this->display();
	}
	
	/**
	 * Details show entity
	 *
	 * @access public
	 * @return void
	 */
	public function showEntity() {
		// Set model state
		$this->setModelState ( 'serverstats' );
		
		$identifier = $this->app->getInput()->get ( 'identifier', null, 'string' );
		$detailType = $this->app->getInput()->get ( 'details' );
		
		$model = $this->getModel ();
		$detailData = $model->loadStatsEntity ( $identifier, $detailType );
		// Try to load record from model
		if ($detailData === false) {
			// Model set exceptions for something gone wrong, so enqueue exceptions and levels on application object then set redirect and exit
			$modelExceptions = $model->getExceptions ();
			foreach ( $modelExceptions as $exception ) {
				$this->app->enqueueMessage ( $exception->getMessage (), $exception->getExceptionLevel () );
			}
			return false;
		}
		
		// Get view always HTML format
		$view = $this->getView ('serverstats', 'html', '', array('base_path' => $this->basePath, 'layout' => 'default'));
		
		// Call main template
		$prefixPath = null;
		if ($this->task === 'showEntitypdf') {
			$prefixPath = 'pdf_';
		}
		if ($this->task === 'showEntitycsv') {
			$prefixPath = 'csv_';
		}
		if ($this->task == 'showEntityxls') {
			$prefixPath = 'xls_';
		}
		$view->setLayout ( $prefixPath . 'details' );
		
		// Creazione buffer output
		ob_start ();
		// Parent construction and view display
		$view->showEntity ( $detailData, $detailType );
		$bufferContent = ob_get_contents ();
		ob_end_clean ();
		
		// Choose if plain HTML or PDF conversion is required based on tasks instead of document format
		switch ($this->task) {
			case 'showEntitypdf' :
				// Do conversion to PDF format using adapter
				$pdfRenderer = new RenderersAdapterPdf ();
				$pdfRenderer->renderContent ( $bufferContent, $model, $detailType . '_stats_report_' );
				break;
			case 'showEntitycsv' :
				$csvRenderer = new RenderersAdapterCsv ();
				$csvRenderer->renderContent ( $bufferContent, $model, $detailType . '_stats_report_' );
				break;
			case 'showEntityxls' :
				$xlsRenderer = new RenderersAdapterXls ();
				$xlsRenderer->renderContent ( $bufferContent, $model, $detailType . '_stats_report_' );
				break;
			default :
				echo $bufferContent;
		}
	}
	
	/**
	 * Cancellazione dati statistici nella DB cache
	 *
	 * @access public
	 * @return bool
	 */
	public function deleteEntity(): bool {
		// Access check
		if (! $this->allowDelete ( $this->option )) {
			$this->setRedirect ( "index.php?option=" . $this->option . "&task=" . $this->name . ".display", Text::_ ( 'COM_JREALTIME_ERROR_ALERT_NOACCESS' ), 'notice' );
			return false;
		}
		
		// Set model state
		$model = $this->setModelState ( 'serverstats' );
		
		if (! $model->deleteEntity ( null )) {
			// Model set exceptions for something gone wrong, so enqueue exceptions and levels on application object then set redirect and exit
			$modelException = $model->getException ( null, false );
			$this->app->enqueueMessage ( $modelException->getMessage (), $modelException->getExceptionLevel () );
			$this->setRedirect ( 'index.php?option=' . $this->option . '&task=' . $this->name . '.display', Text::_ ( 'COM_JREALTIME_ERROR_CLEANED_CACHE' ) );
			return false;
		}
		
		$this->setRedirect ( 'index.php?option=' . $this->option . '&task=' . $this->name . '.display', Text::_ ( 'COM_JREALTIME_SUCCESS_CLEANED_CACHE' ) );
		
		return true;
	}
	
	/**
	 * Fetch host address IP info
	 *
	 * @access public
	 * @return void
	 */
	public function fetchIpinfo() {
		$ipAddress = $this->app->getInput()->getString('ipaddress');
		$ipInformations = gethostbyaddr($ipAddress);
	
		echo $ipInformations;
		jexit();
	}
	
	/**
	 * Overloaded class constructor
	 *
	 * @access public
	 * @return Object&
	 */
	public function __construct($config = array(), ?MVCFactoryInterface $factory = null, $app = null, $input = null) {
		parent::__construct($config, $factory, $app, $input);
		
		// Routes controller tasks
		$this->registerTask ( 'displaypdf', 'display' );
		$this->registerTask ( 'displaycsv', 'display' );
		$this->registerTask ( 'displayxls', 'display' );
		$this->registerTask ( 'showEntitypdf', 'showEntity' );
		$this->registerTask ( 'showEntitycsv', 'showEntity' );
		$this->registerTask ( 'showEntityxls', 'showEntity' );
		$this->registerTask ( 'deletePeriodEntity', 'deleteEntity' );
		$this->registerTask ( 'runaianalysis', 'runaianalysis' );
	}
}