<?php
namespace nur\sery\ext\spreadsheet;

use nur\sery\file\csv\AbstractBuilder;
use nur\sery\file\csv\TAbstractBuilder;
use nur\sery\os\path;
use nur\sery\web\http;
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class PhpSpreadsheetBuilder extends AbstractBuilder {
  use TAbstractBuilder;

  /** @var string|int|null nom de la feuille dans laquelle écrire */
  const WSNAME = null;

  function __construct(?string $output, ?array $params=null) {
    parent::__construct($output, $params);
    $this->ss = new Spreadsheet();
    $this->valueBinder = new StringValueBinder();
    $this->setWsname($params["wsname"] ?? static::WSNAME);
  }

  protected Spreadsheet $ss;

  protected IValueBinder $valueBinder;

  protected ?Worksheet $ws;

  protected int $nrow;

  const STYLE_ROW = 0, STYLE_HEADER = 1;

  protected int $rowStyle;

  /**
   * @param string|int|null $wsname
   */
  function setWsname($wsname): self {
    $ss = $this->ss;
    $this->ws = null;
    $this->nrow = 0;
    $this->rowStyle = self::STYLE_ROW;

    $ws = wsutils::get_ws($wsname, $ss);
    if ($ws === null) {
      $ws = $ss->createSheet()->setTitle($wsname);
      $this->wroteHeaders = false;
    } else {
      $maxRow = wsutils::compute_max_coords($ws)[1];
      $this->nrow = $maxRow - 1;
      $this->wroteHeaders = $maxRow > 1;
    }
    $this->ws = $ws;
    return $this;
  }

  function _write(array $row): void {
    $ws = $this->ws;
    $styleHeader = $this->rowStyle === self::STYLE_HEADER;
    $nrow = ++$this->nrow;
    $ncol = 1;
    foreach ($row as $col) {
      $ws->getCellByColumnAndRow($ncol++, $nrow)->setValue($col, $this->valueBinder);
    }
    if ($styleHeader) {
      $ws->getStyle("$nrow:$nrow")->getFont()->setBold(true);
      $maxcol = count($row);
      for ($ncol = 1; $ncol <= $maxcol; $ncol++) {
        $ws->getColumnDimensionByColumn($ncol)->setAutoSize(true);
      }
    }
  }

  function writeHeaders(?array $headers=null): void {
    $this->rowStyle = self::STYLE_HEADER;
    parent::writeHeaders($headers);
    $this->rowStyle = self::STYLE_ROW;
  }

  function _sendContentType(): void {
    switch (path::ext($this->output)) {
    case ".ods":
      $contentType = "application/vnd.oasis.opendocument.spreadsheet";
      break;
    case ".xlsx":
    default:
      $contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
      break;
    }
    http::content_type($contentType);
  }

  protected function _checkOk(): bool {
    switch (path::ext($this->output)) {
    case ".ods":
      $writer = new Ods($this->ss);
      break;
    case ".xlsx":
    default:
      $writer = new Xlsx($this->ss);
      break;
    }
    $writer->save($this->getResource());
    $this->rewind();
    return true;
  }
}
