<?php

include_once "./lib/exception.php";


class Florm {
    private SQLite3 $db;
    function __construct(string $path, $migrations=[]) {
        $this->db = new SQLite3($path, SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
        $this->_init_migrate($migrations);
    }

    function _init_migrate($migrations) {
        $this->db->exec("create table if not exists version (
                key INTEGER PRIMARY KEY CHECK (key = 0),
                version INTEGER
            )");
        $this->db->exec("insert or ignore into version (key,version) values(0,0)");
        $current_version = $this->query_int("select version from version limit 1");
        if($current_version >= count($migrations)) {
            return;
        }
        for ($x = $current_version; $x < count($migrations); $x++) {
            $this->db->exec($migrations[$x]);
            $this->exec("update version set version = :version",["version"=>$x+1]);
        }

    }

    function exec(string $query, array $bind = []): bool {
        $stmt = $this->db->prepare($query);
        foreach($bind as $key => $value) {
            $stmt->bindParam(":" . $key, $value);
        }
        $executed = $stmt->execute();
        if($executed == false) {
            return false;
        }
        $executed->finalize();
        return true;
    }

    function query_rows(string $query, array $bind = []): array {
        $stmt = $this->db->prepare($query);
        foreach($bind as $key => $value) {
            $stmt->bindParam(":" . $key, $value);
        }
        $executed = $stmt->execute();
        if($executed == false) {
            throw new ExecutionFailedException("query failed");
        }
        $tmp = $executed->fetchArray();
        $executed->finalize();
        if($tmp == false) {
            return [];
        }
        return $tmp;
    }
    function query_row(string $query, array $bind = []): array {
        $rows = $this->query_rows($query, $bind);
        if(count($rows) == 0) {
            throw new NoRowsException("no rows");
        }
        if(is_array($rows[0])) {
            return $rows[0];
        }
        return [$rows[0]];
    }
    function query_int(string $query, array $bind = []): int {
        $row = $this->query_row($query, $bind);
        if(count($row) == 0) {
            throw new InvalidTypeException("expected 1 argument, got 0");
        }
        $intvar = $row[0];
        if (!is_int($intvar)) {
            throw new InvalidTypeException("expected integer");
        }
        return $intvar;
    }

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

?>