<?php
namespace nur\io;

use nur\b\io\IWriter;
use nur\b\io\TmpfileWriter;
use nur\writer;

trait Ttmpwriter {
  protected $ppOutput;

  function pp_setOutput($output): void {
    if ($output instanceof IWriter) $this->writer = $output;
    else $this->ppOutput = $output;
  }

  protected $useTmpfile;

  /**
   * utiliser un fichier temporaire pour la sortie, puis créer $output en une
   * seule fois à la fin, lors de la fermeture de l'objet.
   *
   * $useTmpfile peut être un booléen, mais aussi un nom de fichier: dans ce
   * cas la fonctionnalité n'est activée que si $useTmpfile et $output
   * désignent le même fichier
   */
  function setUseTmpfile($useTmpfile=true): self {
    if (is_string($useTmpfile)) {
      if (writer::is_file($useTmpfile)) {
        $useTmpfile = realpath($useTmpfile) === realpath($this->ppOutput);
      } else {
        $useTmpfile = false;
      }
    }
    $this->useTmpfile = boolval($useTmpfile);
    return $this;
  }

  /** @var IWriter */
  protected $writer;

  protected function buildWriter(bool $appendFilters, ?string $mode): void {
    if ($mode === null) $mode = "w+b";
    $this->writer = writer::with($this->ppOutput, $mode);
    if ($appendFilters) $this->_rwAppendFilters($this->writer);
  }

  /** @var TmpfileWriter */
  protected $tmpwriter;

  protected function getWriter(): IWriter {
    return $this->useTmpfile? $this->tmpwriter: $this->writer;
  }

  protected function setupWriter(bool $useFilters, ?string $mode=null): void {
    if ($this->useTmpfile) {
      $this->tmpwriter = new TmpfileWriter();
    } else if ($this->writer === null) {
      $this->buildWriter($useFilters, $mode);
    }
  }

  protected function ensureWriter(bool $useFilters, ?string $mode=null): IWriter {
    if ($this->writer === null && $this->tmpwriter === null) {
      $this->setupWriter($useFilters, $mode);
    }
    return $this->getWriter();
  }

  protected function teardownWriter(bool $useFilters, ?string $mode=null): void {
    if ($this->tmpwriter !== null) {
      $this->tmpwriter->close();
      $this->buildWriter($useFilters, $mode);
      $this->tmpwriter->getReader()->copyTo($this->writer);
      $this->tmpwriter = null;
    }
    if ($this->writer !== null) {
      $this->writer->close();
      $this->writer = null;
    }
  }
}