<?php
require_once(dirname(__FILE__).'/DbController.php');
require_once(dirname(__FILE__).'/IqdParserController.php');
require_once(dirname(__FILE__).'/../models/CsvConfig.php');

class CsvController 
{
	/** @var  DbController */
	private $db;

	private $conf;

	/** @var CsvConfig */
	private $csv;

	private $data;
	private $header;

	public function __construct($csvConfig = false)
	{
		$this->csv = ($csvConfig) ? $csvConfig : new CsvConfig();
		$this->conf = array("report" => "", "export_query" => "");
	}

    public function csvExport()
	{
        $res = $this->db->Query($this->conf['export_query']);
        if ($this->db->Error($this->conf['export_query'])) return false;
        $firstRow = $res->fetch(PDO::FETCH_ASSOC);
        if (!$firstRow) return false;
        $columns = array_keys($firstRow);
        $this->columnDetails = array();
        for ($i = 0; $i < count($firstRow); $i++) {
            $$this->column_details[$columns[$i]] = $this->getColumnTypeFromQuery($res, $i);
        }
        $header = $this->db->getHeaderNames($this->conf['report'], $columns);
    
        $fwh = fopen($this->conf['filename'], "w");
        fwrite($fwh, implode(';', $header)."\n");
        fwrite($fwh, implode(';', $this->encodeRow($firstRow))."\n");
    
        while($row = $res->fetch(PDO::FETCH_ASSOC)) {
            fwrite($fwh, implode(';', $this->encodeRow($row))."\n");
        }
        fclose($fwh);
        return true;
    }

	public function getHeader ()
	{
		if (!$this->header) {
			$firstRow = $this->getHeaderFromCsv();
			$this->header = ($this->csv->Header) ? $firstRow : $this->getArtificialHeader(count($firstRow));
		}
		return $this->header;
	}

	private function getRow ($handle)
	{
		$row = str_replace("\r\n", "", fgets($handle));
		return ($this->csv->Encoding == "ansi") ? mb_convert_encoding($row, "ISO-8859-1", "UTF-8") : $row;
	}

	public function getHeaderFromCsv ()
	{
		if (($handle = fopen($this->csv->Filename, "r")) === false) return false;
		$header = $this->getRow($handle);
		fclose($handle);
		return $this->getHeaderFromString($header);
	}

	public function getHeaderFromString ($rowString)
	{
		$row = explode($this->csv->Delimiter, $rowString);
		return array_map("IqdParserController::stringConvert", $row);
	}

	public function import ($callback = "CsvController::identity")
	{
		if (($handle = fopen($this->csv->Filename, "r")) === false) return false;

		if ($this->csv->Header) {
			$this->header = $this->getHeaderFromString($this->getRow($handle));
		}

		$result = array();
		while ($row = $this->getRow($handle)) {
			$result[] = call_user_func($callback, $this->decodeRow(explode($this->csv->Delimiter, $row)));
		}
		fclose($handle);
		return $result;
	}

	private static function identity ($var)
	{
		return $var;
	}

	private static function sqlInsert ($var)
	{
		return "('" . implode("','", $var) . "')";
	}


	/**
	 * @param PDOStatement $query
	 * @param string $column
	 * @return string
	 */
	private function getColumnTypeFromQuery($query, $column) {
		$meta = $query->getColumnMeta($column);
		return $meta['native_type'];
	}



    public function convertArray ($tableArray)
    {
        $result = "";
        foreach ($tableArray as $row)
        {
            $result .= $this->encodeRow($row);
        }
        return $result;
    }    

	public function decodeRow ($row)
	{
		if (!$this->header) {
			$this->header = $this->getArtificialHeader(count($row));
		}
		$result = array_combine($this->header, array_fill(0, count($this->header), ''));
		foreach ($row as $i => $col) {
			$result[$this->header[$i]] = $this->decodeColumn($col);
		}
		return $result;
	}

	private function decodeColumn ($col)
	{
		$col = str_replace("\"", "", $col);
		$col = str_replace("'", "", $col);
		$col = trim($col);

		if (preg_match("/^\d+,\d+$/", $col)) {
			return str_replace(",", ".", $col);
		}
		if (preg_match("/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/", $col, $m)) {
			return "{$m[3]}-{$m[2]}-{$m[1]}";
		}
		return $col;
	}

    public function encodeRow ($row) {
		if (!$this->header) {
			$this->header = implode(";", array_keys($row));
			$this->data = array();
		}

        $result = array();
    
        foreach ($row as $key => $value) 
        {
            $result[] = $this->encodeColumn($value);
        }
        $csv = implode(';', $result);
		$this->data[] = $csv;
		return $csv . "\r\n";
    }
    
    private function encodeColumn ($col, $format = "VAR_STRING") {
        switch ($format) {
            case 'VAR_STRING':
                return trim($col);
            case 'FLOAT':
            case 'NEWDECIMAL':
                return number_format($col, 2, ",", "");
            case 'DATE':
                return ($format == '0000-00-00') ? "" : $col;
        }
        return $col;
    }

	public function exportToString ()
	{
		if ($this->csv->Header) {
			array_unshift($this->data, $this->header);
		}
		return implode("\r\n", $this->data);
	}

	private function getArtificialHeader ($count)
	{
		$result = array();
		for ($i = 1; $i <= $count; $i++) {
			$result[] = "col" . $i;
		}
		return $result;
	}
}