#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';

use nur\b\io\CacheFile;
use nur\cli\Application;
use nur\msg;
use nur\path;
use nur\sery\db\Capacitor;
use nur\sery\db\CapacitorChannel;
use nur\sery\db\sqlite\SqliteStorage;
use nur\sery\file\Stream;
use nur\yaml;

Application::run(new class extends Application {
  const ARGS = [
    "merge" => parent::ARGS,
    "purpose" => "gestion d'un capacitor sqlite",
    "usage" => "-f DBFILE -c CHANNEL key=value...",
    ["-f", "--dbfile", "args" => 1,
      "help" => "chemin vers la base de données",
    ],
    ["-t", "--table-name", "args" => 1,
      "help" => "nom de la table porteuse du canal de données",
    ],
    ["-c", "--channel-class", "args" => 1,
      "help" => "nom de la classe dérivée de CapacitorChannel",
    ],
  ];

  protected ?string $dbfile = null;

  protected ?string $tableName = null;

  protected ?string $channelClass = null;

  protected ?array $args = null;

  protected static function isa_cond(string $arg, ?array &$ms=null): bool {
    return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms);
  }

  function main() {
    $dbfile = $this->dbfile;
    if ($dbfile === null) self::die("Vous devez spécifier la base de données");
    if (!file_exists($dbfile)) self::die("$dbfile: fichier introuvable");

    if ($this->channelClass !== null) {
      $channelClass = str_replace("/", "\\", $this->channelClass);
      $channel = new $channelClass;
    } elseif ($this->tableName !== null) {
      $channel = new class($this->tableName) extends CapacitorChannel {
        public function __construct(?string $name=null) {
          parent::__construct($name);
          $this->tableName = $name;
        }
      };
    } else {
      self::die("Vous devez spécifier le canal de données");
    }

    $storage = new SqliteStorage($dbfile);
    $capacitor = new Capacitor($storage, $channel);

    $args = $this->args;
    if (!$args) {
      # lister les id
      $out = new Stream(STDOUT);
      $primaryKeys = $storage->getPrimaryKeys($channel);
      $rows = $storage->db()->all([
        "select",
        "cols" => $primaryKeys,
        "from" => $channel->getTableName(),
      ]);
      $out->fputcsv($primaryKeys);
      foreach ($rows as $row) {
        $rowIds = $storage->getRowIds($channel, $row);
        $out->fputcsv($rowIds);
      }
    } else {
      # afficher les lignes correspondantes
      if (count($args) == 1 && !self::isa_cond($args[0])) {
        $filter = $args[0];
      } else {
        $filter = [];
        $ms = null;
        foreach ($args as $arg) {
          if (self::isa_cond($arg, $ms)) {
            $filter[$ms[1]] = [$ms[2], $ms[3]];
          } else {
            $filter[$arg] = ["not null"];
          }
        }
      }
      $first = true;
      $capacitor->each($filter, function ($item, $row) use (&$first) {
        if ($first) $first = false;
        else echo "---\n";
        yaml::dump($row);
      });
    }
  }
});