<?php
/*
 *
 * @package		ARI Smart Content
 * @author		ARI Soft
 * @copyright	Copyright (c) 2011 www.ari-soft.com. All rights reserved
 * @license		GNU/GPL (http://www.gnu.org/copyleft/gpl.html)
 * 
 */

(defined('_JEXEC') && defined('ARI_FRAMEWORK_LOADED')) or die;

AriKernel::import('Application.ARISmartContent.Providers.ProviderBase');
AriKernel::import('CSV.CSVParser');
AriKernel::import('Utils.Utils');
AriKernel::import('SimpleTemplate.SimpleTemplate');
AriKernel::import('Web.JSON.JSON');

class AriSmartContentProviderCsvFile extends AriSmartContentProviderBase
{
	var $CACHE_TIME = 10;
	
	function getData($source, $filter)
	{
		$file = $this->getFile($source);
		if (empty($file))
			return null;

		$params = $source->Params;
		$csvParser = $this->getParser($source, true, $filter);
		
		if (!empty($params->inputEncoding))
			$csvParser->encoding($params->inputEncoding, 'UTF-8');

		if ($params->autoDetect)
			$csvParser->auto($file);
		else
			$csvParser->parse($file);

		return $csvParser->data;
	}

	function getTotalRecords($source, $filter)
	{
		$data = $this->getData($source, $filter);
		
		return count($data);
	}

	function getColumns($source)
	{
		$columns = array();

		if ($source->Formatter && $source->Formatter->Type)
		{
			$formatter = AriSmartContentFormattersHelper::getFormatter($source->Formatter->Type);

			if ($formatter->isDataTransformed($source->Formatter->Data))
			{
				$data = $this->getData($source, null);
				$data = $formatter->formatData($data, $source->Formatter->Data, null, null);

				if (count($data) == 0)
					return $columns;

				$columnNames = $data[0];
				$columnNames = array_keys($columnNames);
				
				foreach ($columnNames as $columnName)
				{
					$columns[] = array(
						'name' => $columnName
					);
				}

				return $columns;
			}
		}
		
		$file = $this->getFile($source);
		if (empty($file))
			return $columns;

		$f = fopen($file, 'r');
		$line = fgets($f);
		fclose($f);
		
		$params = $source->Params;
		$csvParser = $this->getParser($source, false);
		$csvParser->heading = false;
		
		if (!empty($params->inputEncoding))
			$line = @iconv($params->inputEncoding, 'UTF-8', $line);

		$csvParser->parse($line);
		$data = $csvParser->data;
		if (is_array($data) && count($data) > 0)
		{
			foreach ($data[0] as $columnName)
			{
				$columns[] = array(
					'name' => $columnName
				);
			}
		}

		return $columns;
	}

	private function getFile($source)
	{
		$params = $source->Params;
		$file = trim($params->csvFile);
		if (empty($file)) 
			return null;
		
		if (strpos($file, '{$') !== false)
        {
            $currentUserId = JFactory::getUser()->get('id');
            $jInput = JFactory::getApplication()->input;
            if ($jInput->get('option') == 'com_comprofiler' && $jInput->get('user', null, 'int') > 0)
                $currentUserId = $jInput->get('user', null, 'int');

            $file = str_replace(
                array(
                    '{$UserId}'
                ),
                array(
                    $currentUserId
                ),
                $file
            );
        }

		if (AriUtils::isRemoteResource($file))
		{
			AriKernel::import('Remote.Remote');

			$helper = AriSmartContentApplicationHelper::getInstance();
			$cacheFolder = $helper->getCacheFolder();
			$remote = AriRemote::getInstance();
			$cachedFileName = $remote->saveRemoteFile(
				$file, 
				$cacheFolder, 
				$this->CACHE_TIME, 
				AriUtils::getParam($params, 'remoteMethod', 'auto')
			);
			if (empty($cachedFileName))
				return null;

			$file = $cacheFolder . '/' . $cachedFileName;
		}

		if ($file[0] != '/' && $file[0] != '\\' && (strlen($file) < 2 || $file[1] != ':'))
			$file = JPATH_ROOT . '/' . $file;

		if (!@file_exists($file) || !@is_readable($file)) 
			return null;

		return $file;
	}
	
	private function getParser($source, $addFilters = true, $filter = null)
	{
		$params = $source->Params;

		$csvParser = new AriCSVParser();
		$csvParser->strictMode = (bool)AriUtils::getParam($params, 'strictMode');

        if ($params->sortDir && strtoupper($params->sortDir) == 'DESC')
            $csvParser->sort_reverse = true;

        if ($addFilters)
		{
			if (!empty($params->sortBy)) 
			{
				$csvParser->sort_by = $params->sortBy;
                /*
				if ($params->sortDir && strtoupper($params->sortDir) == 'DESC') 
					$csvParser->sort_reverse = true;*/

				if (!empty($params->sortType))
					$csvParser->sort_type = $params->sortType;
			}

			if (isset($params->heading)) 
				$csvParser->heading = $params->heading;

			if (isset($params->offset) && $params->offset > 0) 
				$csvParser->offset = $params->offset;

			if (isset($params->limit) && $params->limit > 0) 
				$csvParser->limit = $params->limit;

			if ($filter)
			{
				$startOffset = $filter->getConfigValue('startOffset');
				$limit = $filter->getConfigValue('limit');
				if (!is_null($startOffset))
				{
					$csvParser->offset = $startOffset;
					$csvParser->limit = $limit;
				}

				$sortField = $filter->getConfigValue('sortField');
				if (!empty($sortField))
				{
					$sortDir = $filter->getConfigValue('sortDirection');
					
					$csvParser->sort_by = $sortField;
					$csvParser->sort_reverse = (strtoupper($sortDir) == 'DESC');
				}
			}

			//'Date2 equals 40664 OR Date2 equals "40665 Man" OR Start Time equals 12:30:0';
			$csvParser->conditions = $this->getConditions(
				AriUtils::getParam($params, 'filters')
			);
		}

		if (!(bool)AriUtils::getParam($params, 'autoDetect'))
		{
			if ($params->delimiter) 
				$csvParser->delimiter = $params->delimiter;
				
			if ($params->enclosure) 
				$csvParser->enclosure = $params->enclosure;
		}

		return $csvParser;
	}

	private function getConditions($filters)
	{
		$conditions = null;
		if (empty($filters))
			return $conditions;
			
		$filters = json_decode($filters, true);
		if (!is_array($filters) || count($filters) == 0)
			return $conditions;

		$conditions = array();
		foreach ($filters as $filter)
		{
			$colName = trim($filter['col']);
			if (empty($colName))
				continue ;
				
			$op = trim($filter['op']);
			if (empty($op))
				continue ;
				
			$value = trim($filter['value']);
			if (empty($value))
				continue ;

			$condition = $colName . ' ' . $op . ' "' . $this->prepareCondition($value) . '"';

			$conditions[] = $condition;
		}

		return count($conditions) > 0 ? join(' OR ', $conditions) : null;
	}

	private function prepareCondition($condition)
	{
		$user = JFactory::getUser();

		$params = array(
			'UserId' => $user->get('id'),
			'UserGroupId' => $user->get('gid'),
			'UserType' => $user->get('usertype'),
			'UserName' => $user->get('name'),
			'UserLogin' => $user->get('username'),
			'UserBlock' => $user->get('block'),
			'UserEmail' => $user->get('email')
		);

		if (strpos($condition, '{$REQUEST:') !== false)
		{
			$request = $_REQUEST;			
			$params['REQUEST'] = $request;
		}

		$condition = AriSimpleTemplate::parse($condition, $params, true);

		return $condition;
	}

	function isSupportServerSide($source)
	{
		$isSupported = true;
		if ($source->Formatter && $source->Formatter->Type)
		{
			$formatter = AriSmartContentFormattersHelper::getFormatter($source->Formatter->Type);

			if ($formatter->isDataTransformed($source->Formatter->Data))
				$isSupported = false;
		}

		return $isSupported;
	}
}