<?php
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.model');
/**
 * Chart model. Database operations like select, update, insert, check out or check in.
 *
 * @version    1.0.0
 * @author 	   ARTIO s.r.o., http://www.artio.net
 * @package    Charts
 * @subpackage Models
 * @copyright  Copyright (C) 2009 ARTIO s.r.o.. All rights reserved.
 * @since      Version 1.0.0
 */
class ARTIOFusionChartsModelARTIOFusionChart extends JModel
{
    /**
     * Id of manipulated chart from request
     *
     * @access private
     * @var int
     */
    private $_id = null;
    /**
     * Chart data
     *
     * @access private
     * @var TableChart
     */
    private $_data = null;
    /**
     * Constructor, set main params.
     *
     * @access public
     */
    function __construct ()
    {
        parent::__construct();
        $array = JRequest::getVar('cid', array(0), '', 'array');
        $edit = JRequest::getVar('edit', true);
        if ($edit)
        $this->setId((int) $array[0]);
    }
    /**
     * Set chart id snd reset chart data.
     *
     * @access private
     * @param int $id new id
     */
    private function setId ($id)
    {
        $this->_id = $id;
        $this->_data = null;
    }
    /**
     * Check in chart after end editing
     *
     * @access public
     * @return boolean true: succesfull, false: no set id or db error
     */
    function checkin ()
    {
        if ($this->_id) {
            $chart = & $this->getTable();
            if (! $chart->checkin($this->_id)) {
                $this->setError($this->_db->getErrorMsg());
                return false;
            }
            return true;
        }
        return false;
    }
    /**
     * Check out chart for lock during editing
     *
     * @access public
     * @param int $uid user id who locked
     * @return boolean true: succesfull, false: no set id or db error
     */
    function checkout ($uid = null)
    {
        if ($this->_id) {
            if (is_null($uid)) {
                $user = & JFactory::getUser();
                $uid = $user->get('id');
            }
            $chart = & $this->getTable();
            if (! $chart->checkout($uid, $this->_id)) {
                $this->setError($this->_db->getErrorMsg());
                return false;
            }
            return true;
        }
        return false;
    }
    /**
     * Save chart on db
     *
     * @access public
     * @param array $data request data
     * @return boolean true: successfull, false: db error or invalid data
     */
    function store ($data)
    {
        $db = &JFactory::getDBO();
        $row = & $this->getTable();
        $oldAlias = '';
        $oldDatetime = $db->getNullDate();
        //edit existing chart
        if (isset($data['id'])) {
            $id = (int) $data['id'];
            if ($id) {
                $row->load($id); //load old version from db
                $oldAlias = $row->alias; //backup old alias fro delete old xml file
                //backup old datetime for deleting old xml file
                $oldDatetime = $row->modified == $db->getNullDate() ? $row->created : $row->modified;
            }
        }
        if (! $row->bind($data)) {
            $this->setError($this->_db->getErrorMsg());
            return 0;
        }
        $user = &JFactory::getUser();
        $date = &JFactory::getDate();
        if (! $row->id) { //new chart
            $row->created = $date->toMySQL();
            $row->created_by = $user->id;
            $row->modified = $db->getNullDate();
            $row->modified_by = 0;
        } else { //edit chart
            $row->modified = $date->toMySQL();
            $row->modified_by = $user->id;
        }
        $params = JRequest::getVar('params', null, 'post', 'array');
        //save chart params in standard joomla params format
        if (is_array($params)) {
            $txt = array();
            foreach ($params as $k => $v) {
                if (trim($v) != '') {
                    $txt[] = "$k=$v";
                }
            }
            $row->params = implode("\n", $txt);
        }
        //new alias from chart title
        $row->alias = JFilterOutput::stringURLSafe($row->title);
        if (! $row->check()) {
            $this->setError($this->_db->getErrorMsg());
            return 0;
        }
        if (! $row->store()) {
            $this->setError($this->_db->getErrorMsg());
            return 0;
        }
        //insert old alias to object for old xml deleting
        $row->oldAlias = $oldAlias;
        //insert old datetime to object for old xml deleting
        $row->datetime = $oldDatetime;
        //load another chart data
        $chart = ARTIOFusionChartsHelper::loadChart($row->type, $row->category, $row);
        $this->_storeTrendLines($row);
        if ($chart->chartType == 1) {
            $this->_storeSingleData($row);
        } elseif ($chart->chartType == 2) {
            $this->_storeMultiData($row);
        }
        return $row->id;
    }
    /**
     * Save data of single chart type.
     *
     * @access private
     * @param TableChart $row
     */
    private function _storeSingleData ($row)
    {
        $db = &JFactory::getDBO();
        //columns lables
        $itemLabel = JRequest::getVar('item-label', null, 'post', 'array');
        //columns values
        $itemValue = JRequest::getVar('item-value', null, 'post', 'array');
        //columns colors
        $itemColor = JRequest::getVar('item-color', null, 'post', 'array');
        //columns hover texts
        $itemHText = JRequest::getVar('item-htext', null, 'post', 'array');
        //columns links
        $itemLink = JRequest::getVar('item-link', null, 'post', 'array');
        //columns alpha
        $itemAlpha = JRequest::getVar('item-alpha', null, 'post', 'array');
        //columns links
        $itemShow = JRequest::getVar('item-show', null, 'post', 'array');
        //columns is sliced sign
        $itemIsSliced = JRequest::getVar('item-isSliced', null, 'post', 'array');
        $row->data = array();
        //delete old saved chart data
        $query = "DELETE FROM `#__artiofusioncharts_single` WHERE `chart` = '$row->id'";
        $db->setQuery($query);
        $db->query();
        //save new from request arrays
        foreach($itemLabel as $i=>$item){
            $itemShow[$i] = isset($itemShow[$i]) ? 1 : 0;
            $itemIsSliced[$i] = isset($itemIsSliced[$i]) ? 1 : 0;
            $query = "INSERT INTO `#__artiofusioncharts_single` (
                                                          `chart`,
                                                          `label`,
                                                          `value`,
                                                          `color`,	
                                                          `htext`,
                                                          `link`, 
                                                          `alpha`, 	
                                                          `show`, 	
                                                          `isSliced`,
                                                          `order`
                                                          ) 
                          VALUES ('$row->id',
                                  ".$db->Quote($itemLabel[$i]).",
                                  ".$db->Quote($itemValue[$i]).",
                                  ".$db->Quote($itemColor[$i]).",
                                  ".$db->Quote($itemHText[$i]).",
                                  ".$db->Quote($itemLink[$i]).",
                                  ".$db->Quote($itemAlpha[$i]).",
                                  ".$db->Quote($itemShow[$i]).",
                                  ".$db->Quote($itemIsSliced[$i]).",
                                  '$i')";
            $db->setQuery($query);
            $db->query();
            $data = new stdClass();
            $data->label = $itemLabel[$i];
            $data->value = $itemValue[$i];
            $data->color = $itemColor[$i];
            $data->htext = $itemHText[$i];
            $data->link = $itemLink[$i];
            $data->alpha = $itemAlpha[$i];
            $data->show = $itemShow[$i];
            $data->isSliced = $itemIsSliced[$i];
            $row->data[] = $data;
        }
        //generate xml
        $xml = ARTIOFusionChartsHelper::getXMLSingle($row);
        //save xml into file
        $this->_cacheXML($row, $xml);
    }
    /**
     * Store Chart Trend Lines
     *
     * @param TableChart $row
     */
    private function _storeTrendLines ($row)
    {
        $db = &JFactory::getDBO();
        //trend lines start values
        $startValues = JRequest::getVar('line-start-value', null, 'post', 'array');
        //trend lines end values
        $endValues = JRequest::getVar('line-end-value', null, 'post', 'array');
        //trend lines colors
        $colors = JRequest::getVar('line-color', null, 'post', 'array');
        //trend lines display text
        $displays = JRequest::getVar('line-display', null, 'post', 'array');
        //trend lines thickness
        $thickness = JRequest::getVar('line-thickness', null, 'post', 'array');
        //trend lines is trend zones sign
        $zones = JRequest::getVar('line-zone', null, 'post', 'array');
        //trend lines display on top sign
        $tops = JRequest::getVar('line-top', null, 'post', 'array');
        //trend lines alpha chanell
        $alphas = JRequest::getVar('line-alpha', null, 'post', 'array');
        $row->lines = array();
        //delete old saved chart data
        $query = "DELETE FROM `#__artiofusioncharts_trendlines` WHERE `chart` = '$row->id'";
        $db->setQuery($query);
        $db->query();
        //save new from request arrays
        for ($i = 0; $i < count($startValues); $i ++) {
            $zones[$i] = isset($zones[$i]) ? 1 : 0;
            $tops[$i] = isset($tops[$i]) ? 1 : 0;
            $query = "INSERT INTO `#__artiofusioncharts_trendlines` (
                                                          `chart`,
                                                          `start_value`,
                                                          `end_value`,
                                                          `color`,	
                                                          `display`,
                                                          `thickness`, 
                                                          `zone`, 	
                                                          `top`, 	
                                                          `alpha`
                                                          ) 
                          VALUES ('$row->id',
                                  ".$db->Quote($startValues[$i]).",
                                  ".$db->Quote($endValues[$i]).",
                                  ".$db->Quote($colors[$i]).",
                                  ".$db->Quote($displays[$i]).",
                                  ".$db->Quote($thickness[$i]).",
                                  ".$db->Quote($zones[$i]).",
                                  ".$db->Quote($tops[$i]).",
                                  ".$db->Quote($alphas[$i]).")";
            $db->setQuery($query);
            $db->query();
            $line = new stdClass();
            $line->start_value = $startValues[$i];
            $line->end_value = $endValues[$i];
            $line->color = $colors[$i];
            $line->display = $displays[$i];
            $line->thickness = $thickness[$i];
            $line->zone = $zones[$i];
            $line->top = $tops[$i];
            $line->alpha = $alphas[$i];
            $row->lines[] = $line;
        }
    }
    /**
     * Save data of multi chart type
     *
     * @access private
     * @param TableChart $row
     */
    private function _storeMultiData ($row)
    {
        $db = &JFactory::getDBO();
        //delete old chart data
        $queries = array();
        $queries[] = "DELETE FROM `#__artiofusioncharts_set` WHERE `dataset` IN
					     (SELECT `id` FROM `#__artiofusioncharts_dataset` WHERE `chart` = '$row->id')";
        $queries[] = "DELETE FROM `#__artiofusioncharts_dataset` WHERE `chart` = '$row->id'";
        $queries[] = "DELETE FROM `#__artiofusioncharts_category` WHERE `chart` = '$row->id'";
        foreach ($queries as $query) {
            $db->setQuery($query);
            $db->query();
        }
        //chart data rows names like categories
        $categories = JRequest::getVar('chart-category', null, 'post', 'array');
        $params = JRequest::getVar('chart-category-params', null, 'post', 'array');
        $row->categories = array();
        //save categories
        foreach ($categories as $i => $category) {
            $oCategories = new stdClass();
            $oCategories->value = $category;
            $oCategories->params = $params[$i];
            $param = $db->Quote($oCategories->params);
            $category = $db->Quote($category);
            $query = "INSERT INTO `#__artiofusioncharts_category` (`chart`,`value`,`params`,`order`)
			          VALUES ('$row->id',$category,$param,'$i')";
            $db->setQuery($query);
            $db->query();
            $row->categories[] = $oCategories;
        }
        //chart data rows like datasets with label and values
        $datasets = JRequest::getVar('dataset', null, 'post', 'array');
        $dParams = JRequest::getVar('dataset-params', null, 'post', 'array');
        $row->datasets = array();
        //save datasets
        foreach ($datasets as $i => $dataset) {
            $oDatasets = new stdClass();
            $oDatasets->value = $dataset;
            $oDatasets->sets = array();
            $oDatasets->params = $dParams[$i];
            $param = $db->Quote($oDatasets->params);
            $dataset = $db->Quote($dataset);
            $query = "INSERT INTO `#__artiofusioncharts_dataset` (`chart`,`value`,`params`,`order`)
			          VALUES ('$row->id',$dataset,$param,'$i')";
            $db->setQuery($query);
            $db->query();
            //new dataset id
            $id = $db->insertid();
            //dataset values
            $values = JRequest::getVar('dataset-' . $i . '-values', null, 'post', 'array');
            $params = JRequest::getVar('dataset-' . $i . '-value-params', null, 'post', 'array');
            //save values by dataset id
            foreach ($values as $j => $value) {
                $oSets = new stdClass();
                $oSets->value = $value;
                $oSets->params = $params[$j];
                $param = $db->Quote($oSets->params);
                $value = $db->Quote($value);
                $query = "INSERT INTO `#__artiofusioncharts_set` (`dataset`,`value`,`params`,`order`)
			          VALUES ('$id',$value,$param,'$j')";
                $db->setQuery($query);
                $db->query();
                $oDatasets->sets[] = $oSets;
            }
            $row->datasets[] = $oDatasets;
        }
        //generate xml
        $xml = ARTIOFusionChartsHelper::getXMLMulti($row);
        //save xml into file
        $this->_cacheXML($row, $xml);
    }
    /**
     * Remove chart from db
     *
     * @access public
     */
    function remove ()
    {
        $cid = JRequest::getVar('cid', array(), 'default', 'array');
        JArrayHelper::toInteger($cid);
        $db = &JFactory::getDBO();
        $queries = array();
        $ids = implode(',', $cid);
        if (count($cid)) {
            //load chart data to delete xml files
            $query = "SELECT `id`,`alias`,`created`,`modified` FROM `#__artiofusioncharts` WHERE `id` IN ($ids)";
            $db->setQuery($query);
            $charts = $db->loadObjectList();
            foreach ($charts as $chart) {
                $datetime = $chart->modified == $db->getNullDate() ? $chart->created : $chart->modified;
                $this->_cleanCache($chart->id, $chart->alias, $datetime);
            }
            $queries[] = "DELETE FROM `#__artiofusioncharts` WHERE `id` IN ($ids)";
            $queries[] = "DELETE FROM `#__artiofusioncharts_single` WHERE `chart` IN ($ids)";
            $queries[] = "DELETE FROM `#__artiofusioncharts_set` WHERE `dataset` IN
						(SELECT `id` FROM `#__artiofusioncharts_dataset` WHERE `chart`	IN ($ids))";
            $queries[] = "DELETE FROM `#__artiofusioncharts_dataset` WHERE `chart` IN ($ids)";
            $queries[] = "DELETE FROM `#__artiofusioncharts_category` WHERE `chart` IN ($ids)";
            foreach ($queries as $query) {
                $db->setQuery($query);
                $db->query();
            }
        }
    }
    /**
     * Save Fusion Charts xml file
     *
     * @access private
     * @param TableChart $chart
     * @param string $xml xml source
     */
    private function _cacheXML ($chart, $xml)
    {
        $db = &JFactory::getDBO();
        //for xml name is use datetime: modified if not null or created
        $datetime = $chart->modified == $db->getNullDate() ? $chart->created : $chart->modified;
        //delete old
        $this->_cleanCache($chart->id, $chart->oldAlias, $chart->datetime);
        //genrate xml name
        $file = ARTIOFusionChartsHelper::getXMLName($chart->id, $chart->alias, $datetime);
        file_put_contents($file, $xml);
    }
    /**
     * Delete old xml source
     *
     * @access private
     * @param int $id chart id
     * @param string $alias chart title alias
     * @param string $datetime modified or created chart datetime
     */
    private function _cleanCache ($id, $alias, $datetime)
    {
        $file = ARTIOFusionChartsHelper::getXMLName($id, $alias, $datetime);
        if (file_exists($file)) {
            unlink($file);
        }
    }
    /**
     * Get chart id
     *
     * @access public
     * @param int $id
     * @return int
     */
    function getId ($id = null)
    {
        return $id === null ? $this->_id : $id;
    }
    /**
     * Get chart data from db
     *
     * @access public
     * @param int $id
     * @return stdClass
     */
    function getData ($id = null)
    {
        $id = ARTIOFusionChartsModelARTIOFusionChart::getId($id);
        $chart = &$this->getTable();
        $chart->load($this->_id);
        return $chart;
    }
    /**
     * Get single chart type data
     *
     * @access public
     * @param stdClass $chart object with main chart settings
     * @param int $id
     */
    function getDataSingle (&$chart, $id = null)
    {
        $db = &JFactory::getDBO();
        $id = ARTIOFusionChartsModelARTIOFusionChart::getId($id);
        $config = JComponentHelper::getParams(ARTIOFUSIONCHARTS_OPTION);
        if (! $id && (int) $config->get('sample_data_sc', 1)) {
            ARTIOFusionChartsHelper::getSigleChartEmptySet($chart, (int) $config->get('sample_data_sc_num_cl', 4));
        } else {
            $query = "SELECT * FROM `#__artiofusioncharts_single` WHERE `chart` = '$id' ORDER BY `order` ASC";
            $db->setQuery($query);
            $chart->data = $db->loadObjectList();
        }
    }
    /**
     * Get multi type chart data
     *
     * @access public
     * @param stdClass $chart object with main chart settings
     * @param int $id
     */
    function getDataMulti (&$chart, $id = null)
    {
        $db = &JFactory::getDBO();
        $id = ARTIOFusionChartsModelARTIOFusionChart::getId($id);
        $config = JComponentHelper::getParams(ARTIOFUSIONCHARTS_OPTION);
        if (! $id && (int) $config->get('sample_data_mc', 1)) {
            ARTIOFusionChartsHelper::getMultiChartEmptyCategories($chart, (int) $config->get('sample_data_mc_num_ct', 4));
        } else {
            $query = "SELECT `value`,`params` FROM `#__artiofusioncharts_category` WHERE `chart` = '$id' ORDER BY `order` ASC";
            $db->setQuery($query);
            $chart->categories = $db->loadObjectList();
        }
        if (! $id && (int) $config->get('sample_data_mc', 1)) {
            ARTIOFusionChartsHelper::getMultiChartEmptyDataset($chart, count($chart->categories), (int) $config->get('sample_data_mc_num_ds', 4));
        } else {
            $query = "SELECT `id`,`value`,`params` FROM `#__artiofusioncharts_dataset` WHERE `chart` = '$id' ORDER BY `order` ASC";
            $db->setQuery($query);
            $chart->datasets = $db->loadObjectList();
            foreach ($chart->datasets as $dataset) {
                $query = "SELECT `value`,`params` FROM `#__artiofusioncharts_set` WHERE `dataset` = '$dataset->id' ORDER BY `order` ASC";
                $db->setQuery($query);
                $dataset->sets = $db->loadObjectList();
            }
        }
    }
    /**
     * Get Chart Trend Lines Data
     *
     * @param stdClass $chart
     * @param int $id
     */
    function getTrendLines (&$chart, $id = null)
    {
        $db = &JFactory::getDBO();
        $id = ARTIOFusionChartsModelARTIOFusionChart::getId($id);
        $query = "SELECT * FROM `#__artiofusioncharts_trendlines` WHERE `chart` = '$id'";
        $db->setQuery($query);
        $chart->lines = $db->loadObjectList();
    }
}
?>