<?php

namespace Snaju\Inception\Api;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Collections\Criteria;
use Snaju\Inception\Annotation\ApiModel;
use Snaju\Inception\Annotation\ProtectedField;
use Snaju\Inception\ORM\DataModel;
use Snaju\Inception\Util\AnnotationHelper;

class ApiUtility
{

    public static function criteriaFromQueryString(Criteria &$criteria, string $q)
    {
        preg_match_all('/((and|or)?(.*?)\s(is|gt|lt|lte|gte|like|not|null|notnull)\s(.*?)(\s|[[:>:]]))/', $q, $m, PREG_SET_ORDER, 0);

        foreach ($m as $match) {
            if (!isset($match[2])) {
                $criteria->where(self::buildExpressionFromString($match[3], $match[4], $match[5]));
            } else {
                if ($match[2] == "and") {
                    $criteria->andWhere(self::buildExpressionFromString($match[3], $match[4], $match[5]));
                } else if ($match[2] == "or") {
                    $criteria->orWhere(self::buildExpressionFromString($match[3], $match[4], $match[5]));
                }
            }
        }

        return $criteria;
    }

    public static function buildExpressionFromString(string $field, string $func, string $compare)
    {
        if ($func == "eq") {
            return Criteria::expr()->eq($field, $compare);
        } else if ($func == "gt") {
            return Criteria::expr()->gt($field, $compare);
        } else if ($func == "gte") {
            return Criteria::expr()->gte($field, $compare);
        } else if ($func == "lt") {
            return Criteria::expr()->lt($field, $compare);
        } else if ($func == "lte") {
            return Criteria::expr()->lte($field, $compare);
        } else if ($func == "like") {
            return Criteria::expr()->contains($field, $compare);
        } else if ($func == "null") {
            return Criteria::expr()->isNull($field);
        } else if ($func == "notnull") {
            return Criteria::expr()->neq($field, null);
        } else if ($func == "neq") {
            return Criteria::expr()->neq($field, $compare);
        }

        return null;
    }

    public static function getParams(string $class, string $mode)
    {

        $params = [];

        $reader = new AnnotationReader();

        $obj = new $class();
        if ($obj instanceof DataModel && $obj instanceof ApiInterface) {

            $refClass = new \ReflectionClass($class);

            /*
             * Is a DataModel and a ApiInterface
             * */
            if ($reader->getClassAnnotation($refClass, ApiModel::class) != null) {
                // Is a ApiModel

                foreach ($refClass->getProperties() as $property) {
                    if ($property instanceof \ReflectionProperty) {

                        $propAnnon = $reader->getPropertyAnnotation($property, ProtectedField::class);

                        if ($propAnnon instanceof ProtectedField) {
                            if ($propAnnon->readable && $mode == "r") {
                                $params[] = $property->getName();
                            }
                            if ($propAnnon->writable && $mode == "w") {
                                $params[] = $property->getName();
                            }
                        } else {
                            // Is not protected
                            $params[] = $property->getName();
                        }

                    }
                }

            }

        }

        return $params;
    }

}