<?php

namespace Signteer\Core\Finder;

use Plainwork\Database\Database;
use Plainwork\Database\Query;
use Signteer\Core\Model\Volunteer;
use Signteer\Core\Criteria\VolunteerCriteria as Criteria;
use Signteer\Core\Database\VolunteerTable as Table;

class VolunteerFinder
{
    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->getWhereTitle() as [$compare, $v]) {
            $q = $q->whereString(Table::NAME . '.' . Table::COL_TITLE, $compare, $v);
        }

        foreach ($c->getWhereEmail() as [$compare, $v]) {
            $q = $q->whereString(Table::NAME . '.' . Table::COL_EMAIL, $compare, $v);
        }

        foreach ($c->getWherePhone() as [$compare, $v]) {
            $q = $q->whereString(Table::NAME . '.' . Table::COL_PHONE, $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 . ')');
        $q->from(Table::NAME);

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

        return $ret;
    }

    public function find(Criteria $c, $sort = null, int $limit = 0, int $offset = 0): array
    {
        $ret = [];

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

        $q->select(Table::COL_ID);
        $q->select(Table::COL_TITLE);
        $q->select(Table::COL_EMAIL);
        $q->select(Table::COL_PHONE);
        $q->from(Table::NAME);

        $q->orderAsc(Table::COL_TITLE);

        if ($limit) {
            $q->limit($limit);
        }
        if ($offset) {
            $q->offset($offset);
        }

        $rows = $q->execute();
        foreach ($rows as $r) {
            $m = new Volunteer(
                $r[Table::COL_ID],
                $r[Table::COL_TITLE],
                $r[Table::COL_EMAIL],
                $r[Table::COL_PHONE],
            );
            $ret[$m->getId()] = $m;
        }

        return $ret;
    }

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

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

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

        $rows = $q->execute();
        foreach ($rows as $r) {
            $ret[$r[Table::COL_ID]] = $r[Table::COL_ID];
        }

        return $ret;
    }

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

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