<?php


namespace App\Tables;


use App\Models\Table;

/**
 * Table exporter base class
 */
abstract class BaseExporter
{
    /**
     * @var Table the table to export
     */
    protected $table;

    /**
     * @var Column[] - parsed columns for the table
     */
    protected $columns;

    /**
     * @var bool - true if user wants download; can e.g. change mime type to text/plain if not
     */
    protected $wantDownload;

    /**
     * TODO export options from enabled columns, sorts, etc
     *
     * @param Table $table
     */
    public function __construct(Table $table)
    {
        $this->table = $table;
        $this->columns = Column::columnsFromJson($table->revision->columns);
    }

    protected function getHeaderComment($prefix = " ")
    {
        $table = $this->table;
        $owner = $this->table->owner;

        $s =
            $prefix."Table \"$table->title\" by $owner->title\n".
            $prefix."exported ".date('M n, Y \\a\\t G:i')."\n".
            $prefix."\n".
            $prefix."License: ". str_replace("\n", "\n$prefix", $table->license ?: 'CC0') ."\n".
            $prefix."\n".
            $prefix."Upstream: https://datatable.directory/$owner->handle/$table->name\n";

        $s .=
            $prefix."\n".
            $prefix."Columns:\n";

        foreach ($this->columns as $c) {
            $s .= $prefix." - $c->name ... $c->title\n";
        }

        return $s;
    }

    /**
     * @return string - mime type for the downloaded file
     */
    protected abstract function getMimeType();

    /**
     * @return string - file extension for the downloaded file
     */
    protected abstract function getFileExtension();

    /**
     * @return string - file name without extension, by default the table name
     */
    protected function getFileBasename()
    {
        return $this->table->name;
    }

    /**
     * Generate a response that appears as a file download to the browser
     *
     * @param bool $download - force download, otherwise the browser may show it in the window
     */
    public function exportToBrowser($download = true)
    {
        $this->wantDownload = $download;

        $mimeType = $this->getMimeType();
        $filename = $this->getFileBasename() . '.' . $this->getFileExtension();

        ob_end_clean();

        // Redirect output to a client’s web browser
        header("Content-Type: $mimeType; charset=utf-8");

        if ($download) {
            header("Content-Disposition: attachment;filename=\"$filename\"");
        }

        // Cache headers
        header('Cache-Control: max-age=0');
        // IE9
        header('Cache-Control: max-age=1');
        // Other IE headers
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
        header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
        header('Pragma: no-cache'); // HTTP/1.0

        $this->writeDocument();
        exit;
    }

    /**
     * Generator that produces PHP arrays for all rows, fetched from the DB in given chunks.
     *
     * @param int $chunkSize - size of one chunk
     * @return \Generator|array[]
     */
    protected function iterateRows($chunkSize = 1000)
    {
        $revision = $this->table->revision;

        $count = $revision->rows()->count();

        $start = 0;
        while ($start < $count) {
            $rows = $revision->rows()->offset($start)->limit($chunkSize)->get();

            foreach ($rows as $row) {
                $data = $row->data;

                // column renaming, value formatting...

                yield $data;
            }

            $start += $chunkSize;
        }
    }

    /**
     * Write the document to stdout ('php://output')
     */
    protected abstract function writeDocument();
}