<?php
namespace nur\sery\db\sqlite;

use nur\sery\db\CapacitorChannel;
use nur\sery\db\CapacitorStorage;

/**
 * Class SqliteStorage
 */
class SqliteStorage extends CapacitorStorage {
  function __construct($sqlite) {
    $this->db = Sqlite::with($sqlite);
  }

  /** @var Sqlite */
  protected $db;

  function db(): Sqlite {
    return $this->db;
  }

  const PRIMARY_KEY_DEFINITION = [
    "id_" => "integer primary key autoincrement",
  ];

  function _getCreateSql(CapacitorChannel $channel): string {
    $query = new _query_base($this->_createSql($channel));
    return self::format_sql($channel, $query->getSql());
  }

  function tableExists(string $tableName): bool {
    $name = $this->db->get([
      # depuis la version 3.33.0 le nom officiel de la table est sqlite_schema,
      # mais le nom sqlite_master est toujours valable pour le moment
      "select name from sqlite_master ",
      "where" => ["name" => $tableName],
    ]);
    return $name !== null;
  }

  function channelExists(string $name): bool {
    $name = $this->db->get([
      "select name from _channels",
      "where" => ["name" => $name],
    ]);
    return $name !== null;
  }

  protected function _afterCreate(CapacitorChannel $channel): void {
    $db = $this->db;
    if (!$this->tableExists("_channels")) {
      # ne pas créer si la table existe déjà, pour éviter d'avoir besoin d'un
      # verrou en écriture
      $db->exec([
        "create table if not exists",
        "table" => "_channels",
        "cols" => [
          "name" => "varchar primary key",
          "table_name" => "varchar",
          "class" => "varchar",
        ],
      ]);
    }
    if (!$this->channelExists($channel->getName())) {
      # ne pas insérer si la ligne existe déjà, pour éviter d'avoir besoin d'un
      # verrou en écriture
      $db->exec([
        "insert",
        "into" => "_channels",
        "values" => [
          "name" => $channel->getName(),
          "table_name" => $channel->getTableName(),
          "class" => get_class($channel),
        ],
        "suffix" => "on conflict do nothing",
      ]);
    }
  }

  protected function _beforeReset(CapacitorChannel $channel): void {
    $this->db->exec([
      "delete",
      "from" => "_channels",
      "where" => [
        "name" => $channel->getName(),
      ],
    ]);
  }

  function _exists(CapacitorChannel $channel): bool {
    return $this->tableExists($channel->getTableName());
  }

  function close(): void {
    $this->db->close();
  }
}
