<?php
defined('VSIGN') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");

class DataSet extends Data
{
    /**
     * Add a data set
     * @param <type> $dataSet
     * @param <type> $description
     * @param <type> $userId
     * @return <type>
     */
    public function Add($dataSet, $description, $userId)
    {
        $db =& $this->db;

        // Validation
        if (strlen($dataSet) > 50 || strlen($dataSet) < 1)
        {
            $this->SetError(25001, __("Name must be between 1 and 50 characters"));
            return false;
        }

        if (strlen($description) > 254)
        {
            $this->SetError(25002, __("Description can not be longer than 254 characters"));
            return false;
        }

        // Ensure there are no layouts with the same name
        $SQL = sprintf("SELECT DataSet FROM dataset WHERE DataSet = '%s' ", $dataSet);

        if ($db->GetSingleRow($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25004, sprintf(__("There is already dataset called '%s'. Please choose another name."), $dataSet));
            return false;
        }
        // End Validation

        $SQL = "INSERT INTO dataset (DataSet, Description, UserID) ";
        $SQL .= " VALUES ('%s', '%s', %d) ";

        if (!$id = $db->insert_query(sprintf($SQL, $dataSet, $description, $userId)))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Could not add DataSet'));

            return false;
        }

        Debug::LogEntry($db, 'audit', 'Complete', 'DataSet', 'Add');

        return $id;
    }

    /**
     * Edit a DataSet
     * @param <type> $dataSetId
     * @param <type> $dataSet
     * @param <type> $description
     */
    public function Edit($dataSetId, $dataSet, $description)
    {
        $db =& $this->db;

        // Validation
        if (strlen($dataSet) > 50 || strlen($dataSet) < 1)
        {
            $this->SetError(25001, __("Name must be between 1 and 50 characters"));
            return false;
        }

        if (strlen($description) > 254)
        {
            $this->SetError(25002, __("Description can not be longer than 254 characters"));
            return false;
        }

        // Ensure there are no layouts with the same name
        $SQL = sprintf("SELECT DataSet FROM dataset WHERE DataSet = '%s' AND DataSetID <> %d ", $dataSet, $dataSetId);

        if ($db->GetSingleRow($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25004, sprintf(__("There is already a dataset called '%s'. Please choose another name."), $dataSet));
            return false;
        }
        // End Validation

        $SQL = "UPDATE dataset SET DataSet = '%s', Description = '%s' WHERE DataSetID = %d ";
        $SQL = sprintf($SQL, $dataSet, $description, $dataSetId);

        if (!$db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, sprintf(__('Cannot edit dataset %s'), $dataSet));
            return false;
        }

        return true;
    }

    /**
     * Delete DataSet
     * @param <type> $dataSetId
     */
    public function Delete($dataSetId)
    {
        $db =& $this->db;

        Kit::ClassLoader('datasetgroupsecurity');
        $security = new DataSetGroupSecurity($db);
        $security->UnlinkAll($dataSetId);
        
        // get dataSetColumnID
        $SQL = "SELECT DataSetColumnID FROM datasetcolumn WHERE DataSetID = %d";
        $SQL = sprintf($SQL, $dataSetId);
        if (!$result = $db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Cannot delete dataset'));
            return false;
        }
        if($db->num_rows($result) > 0)
        {
            while($row = $db->get_assoc_row($result))
            {
                $SQL = "DELETE FROM datasetdata WHERE DataSetColumnID = %d";
                $SQL = sprintf($SQL, $row['DataSetColumnID']);
                if(!$db->query($SQL))
                {
                    trigger_error($db->error());
                    $this->SetError(25005, __('Cannot delete dataset'));
                    return false;
                }
            }
            $SQL = "DELETE FROM datasetcolumn WHERE DataSetID = %d";
            $SQL = sprintf($SQL, $dataSetId);        
            if (!$db->query($SQL))
            {
                trigger_error($db->error());
                $this->SetError(25005, __('Cannot delete dataset'));
                return false;
            }
        }
        
        $SQL = "DELETE FROM dataset WHERE DataSetID = %d";
        $SQL = sprintf($SQL, $dataSetId);

        if (!$db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Cannot delete dataset'));
            return false;
        }
        
        return true;
    }

    /**
     * Clear DataSet (delete column and contents)
     * @param <type> $dataSetId
     */
    public function Clear($dataSetId)
    {
        $db =& $this->db;

        // get dataSetColumnID
        $SQL = "SELECT DataSetColumnID FROM datasetcolumn WHERE DataSetID = %d";
        $SQL = sprintf($SQL, $dataSetId);
        if (!$result = $db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Cannot delete dataset'));
            return false;
        }
        if($db->num_rows($result) > 0)
        {
            while($row = $db->get_assoc_row($result))
            {
                $SQL = "DELETE FROM datasetdata WHERE DataSetColumnID = %d";
                $SQL = sprintf($SQL, $row['DataSetColumnID']);
                if(!$db->query($SQL))
                {
                    trigger_error($db->error());
                    $this->SetError(25005, __('Cannot delete dataset'));
                    return false;
                }
            }
            $SQL = "DELETE FROM datasetcolumn WHERE DataSetID = %d";
            $SQL = sprintf($SQL, $dataSetId);        
            if (!$db->query($SQL))
            {
                trigger_error($db->error());
                $this->SetError(25005, __('Cannot delete dataset'));
                return false;
            }
        }
        
        return true;
    }
    
    public function Import($dataSetId,$fileId)
    {
        $db =& $this->db;
        
        // baris mulai dari 1 - highestrow, kolom mulai dari 0 - (columnindex - 1)        
        require_once '3rdparty/phpexcel/PHPExcel.php';
        $libraryFolder  = Config::GetSetting($db, 'LIBRARY_LOCATION');
        $inputFileName   = $libraryFolder . 'temp/' . $fileId;
        $inputFileType = PHPExcel_IOFactory::identify($inputFileName);
        $objReader = PHPExcel_IOFactory::createReader($inputFileType);
        if($objReader->canRead($inputFileName))
        {
            $objReader->setReadDataOnly(true);
            $objPHPExcel = $objReader->load($inputFileName);
            $objWorksheet = $objPHPExcel->getSheet(0);
            $highestRow = $objWorksheet->getHighestRow(); // e.g. 10
            $highestColumn = $objWorksheet->getHighestColumn(); // e.g 'F'
            $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn); // e.g. 5

            
            $selesai = false;
            $startrow = 0;
            for($i=1;$i<=$highestRow;$i++)
            {
              if($selesai)
              {
                break;
              }
              
              for($j=0;$j<$highestColumnIndex;$j++)
              {
                if(!is_null($objWorksheet->getCellByColumnAndRow($j, $i)->getValue()))
                {
                  //echo $j.":".$i.EOL;
                  $selesai = true;
                  $startrow = $i;
                  break;
                }
              }
            }

            $selesai = false;
            $startcol = 0;
            for($j=0;$j<$highestColumnIndex;$j++)
            {
              if($selesai)
              {
                break;
              }

              for($i=$startrow;$i<$highestRow;$i++)
              {
                if(!is_null($objWorksheet->getCellByColumnAndRow($j, $i)->getValue()))
                {
                  //echo $j.":".$i.EOL;
                  $selesai = true;
                  $startcol = $j;
                  break;
                }
              }
            }
        }
        
        $listContent = "";
        $columnOrder = 0;
        $dataSetColumnId = 0;
        
        $dataSetData = new DataSetData($db);
        $dataSetColumn= new DataSetColumn($db);
        for($j=$startcol;$j<$highestColumnIndex;$j++)
        {
            for($i=$startrow;$i<=$highestRow;$i++)
            {
                if($i==$startrow)
                {
                    $heading = $objWorksheet->getCellByColumnAndRow($j, $i)->getCalculatedValue();
                    $columnOrder = $j - $startcol + 1;
                    if(is_null($heading))
                    {
                        $heading = "Col".$columnOrder;
                    }
                    if (!$id=$dataSetColumn->Add($dataSetId, $heading, 1, $listContent, $columnOrder ))
                    {
                        trigger_error($db->error());
                        $this->SetError(25005, __('Cannot add dataset column'));
                        return false;
                    }
                    $dataSetColumnId = $id;
                }
                else
                {
                    $value= $objWorksheet->getCellByColumnAndRow($j, $i)->getCalculatedValue();
                    $rowOrder = $i - $startrow;
                    if(is_null($value))
                        continue;
                    if (!$dataSetData->Add($dataSetColumnId, $rowOrder, $value))
                    {
                        trigger_error($db->error());
                        $this->SetError(25005, __('Cannot add dataset data'));
                        return false;
                    }
                }
            }
        }
            
        return true;
    }
    
    public function LinkLayout($dataSetId, $layoutId, $regionId, $mediaId) {
        $db =& $this->db;
        
        $SQL = sprintf("INSERT INTO `lkdatasetlayout` (DataSetID, LayoutID, RegionID, MediaID) VALUES ('%d','%d','%s','%s')",$dataSetId, $layoutId, $regionId, $mediaId);
        
        if (!$db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Cannot link dataset'));
            return false;
        }
        
        return true;
    }
    
    public function UnlinkLayout($dataSetId, $layoutId, $regionId, $mediaId) {
        $db =& $this->db;
        $SQL = sprintf("DELETE FROM `lkdatasetlayout` WHERE DataSetID = '%d' AND LayoutID = '%d' AND RegionID = '%s' AND MediaID = '%s' ",$dataSetId, $layoutId, $regionId, $mediaId);
        if (!$db->query($SQL))
        {
            trigger_error($db->error());
            $this->SetError(25005, __('Cannot unlink dataset'));
            return false;
        }
        
        return true;
    }

    /**
     * Data Set Results
     * @param <type> $dataSetId
     * @param <type> $columnIds
     * @param <type> $filter
     * @param <type> $ordering
     * @param <type> $lowerLimit
     * @param <type> $upperLimit
     * @return <type>
     */
    public function DataSetResults($dataSetId, $columnIds, $filter = '', $ordering = '', $lowerLimit = 0, $upperLimit = 0)
    {
        $db =& $this->db;

        $selectSQL = '';
        $outserSelect = '';
        $results = array();
        $headings = array();
        
        $columns = explode(',', $columnIds);

        // Get all columns for the cross tab
        $allColumns = $db->GetArray(sprintf('SELECT DataSetColumnID, Heading FROM datasetcolumn WHERE DataSetID = %d' , $dataSetId));

        foreach($allColumns as $col)
        {
            $heading = $col;
            
            if (in_array($col['DataSetColumnID'], $columns))
                $headings[] = $heading;

            $selectSQL .= sprintf("MAX(CASE WHEN DataSetColumnID = %d THEN `Value` ELSE null END) AS '%s', ", $col['DataSetColumnID'], $heading['Heading']);
        }

        // For each heading, put it in the correct order (according to $columns)
        foreach($columns as $visibleColumn)
        {
            // Check to see if this column is in the headings
            foreach($headings as $heading)
            {
                if ($heading['DataSetColumnID'] == $visibleColumn)
                {
                    $outserSelect .= sprintf(' `%s`,', $heading['Heading']);
                    $results['Columns'][] = $heading['Heading'];
                }
            }
        }

        $outserSelect = rtrim($outserSelect, ',');

        // We are ready to build the select and from part of the SQL
        $SQL  = "SELECT $outserSelect ";
        $SQL .= "  FROM ( ";
        $SQL .= "   SELECT $selectSQL ";
        $SQL .= "       RowNumber ";
        $SQL .= "     FROM (";
        $SQL .= "       SELECT datasetcolumn.DataSetColumnID, datasetdata.RowNumber, datasetdata.`Value` ";
        $SQL .= "         FROM datasetdata ";
        $SQL .= "           INNER JOIN datasetcolumn ";
        $SQL .= "           ON datasetcolumn.DataSetColumnID = datasetdata.DataSetColumnID ";
        $SQL .= sprintf("       WHERE datasetcolumn.DataSetID = %d ", $dataSetId);
        $SQL .= "       ) datasetdatainner ";
        $SQL .= "   GROUP BY RowNumber ";
        $SQL .= " ) datasetdata ";
        if ($filter != '')
        {
            $where = ' WHERE 1 = 1 ';

            $filter = explode(',', $filter);

            foreach ($filter as $filterPair)
            {
                $filterPair = explode('=', $filterPair);
                $where .= sprintf(" AND %s = '%s' ", $filterPair[0], $db->escape_string($filterPair[1]));
            }

            $SQL .= $where . ' ';
        }

        if ($ordering != '')
        {
            $order = ' ORDER BY ';

            $ordering = explode(',', $ordering);

            foreach ($ordering as $orderPair)
            {
                if (strripos($orderPair, ' DESC'))
                {
                    $orderPair = str_replace(' DESC', '', $orderPair);
                    $order .= sprintf(" `%s` DESC,", $db->escape_string($orderPair));
                }
                else
                {
                    $order .= sprintf(" `%s`,", $db->escape_string($orderPair));
                }
            }

            $SQL .= trim($order, ',');
        }
        else
        {
            $SQL .= "ORDER BY RowNumber ";
        }

        // jika dua2nya tidak nol atau negatif
        if ($lowerLimit > 0 && $upperLimit > 0)
        {
            // Jika upperlimit lebih kecil, anggap sama dengan 0 (unlimited)
            if ($lowerLimit >= $upperLimit)
            {
                $lowerLimit--;
                $SQL .= sprintf('LIMIT %d, 1234567890 ', $lowerLimit);
            }
            else
            {
                $lowerLimit--;
                $count = $upperLimit - $lowerLimit;
                $SQL .= sprintf('LIMIT %d, %d ', $lowerLimit, $count);
            }
        }
        // jika lowerLimit saja yang diset
        else if ($lowerLimit > 0)
        {
            $lowerLimit--;
            $SQL .= sprintf('LIMIT %d, 1234567890 ', $lowerLimit);
        }
        // jika upperLimit saja yang diset
        else if ($upperLimit > 0)
        {
            $SQL .= sprintf('LIMIT %d ', $upperLimit);
        }

        Debug::LogEntry($db, 'audit', $SQL);

        if (!$rows = $db->GetArray($SQL, false))
            trigger_error($db->error());
            
        $results['Rows'] = $rows;

        return $results;
    }
}
?>