<?php

namespace Signteer\Core\Finder;

use Plainwork\Database\Database;
use Plainwork\Database\Query;
use Signteer\Core\Criteria\TaskCriteria as Criteria;
use Signteer\Core\Model\Task;
use Signteer\Core\Database\TaskTable as Table;

class TaskFinder
{
    public $db = Database::class;
    public $table = Table::class;

    public function applyCriteriaToQuery(Query $q, Criteria $c): Query
    {
        foreach ($c->getWhereId() as [$compare, $v]) {
            $q = $q->whereInt(Table::NAME . '.' . Table::COL_ID, $compare, $v);
        }
        foreach ($c->getWhereSheetId() as [$compare, $v]) {
            $q = $q->whereInt(Table::NAME . '.' . Table::COL_SHEET_ID, $compare, $v);
        }
        foreach ($c->getWhereTitle() as [$compare, $v]) {
            $q = $q->whereString(Table::NAME . '.' . Table::COL_TITLE, $compare, $v);
        }

        return $q;
    }

    public function exists(Criteria $c): bool
    {
        $q = $this->db->q();
        $q = $this->applyCriteriaToQuery($q, $c);

        $q->select(1)->from(Table::NAME)->limit(1);
        $res = $q->execute();

        return ($res) ? true : false;
    }

    public function count(Criteria $c): int
    {
        $q = $this->db->q();
        $q = $this->applyCriteriaToQuery($q, $c);

        $q->select('COUNT(' . Table::COL_ID . ')')->from(Table::NAME);

        $res = $q->execute();
        $ret = $res ? current(current($res)) : 0;

        return $ret;
    }

    public function find(Criteria $c): array
    {
        $ret = [];

        $q = $this->db->q();
        $q = $this->applyCriteriaToQuery($q, $c);

        $q->select(Table::COL_ID);
        $q->select(Table::COL_SHEET_ID);
        $q->select(Table::COL_TITLE);
        $q->select(Table::COL_SPOTS);
        $q->from(Table::NAME);
        $q->orderAsc(Table::COL_TITLE);

        $rows = $q->execute();

        foreach ($rows as $r) {
            $m = new Task(
                $r[Table::COL_ID],
                $r[Table::COL_SHEET_ID],
                $r[Table::COL_TITLE],
                $r[Table::COL_SPOTS],
            );
            $ret[$m->getId()] = $m;
        }

        return $ret;
    }

    public function get(int $id): ?Task
    {
        $c = (new Criteria())->whereId('=', $id);
        $res = $this->find($c);

        return $res ? current($res) : null;
    }
}
