<?php

namespace FCA\StockApi\Collection\Filter;

use FCA\StockApi\Collection\Filter\Builder\Fields;
use FCA\StockApi\Exception\ApiException;

class Stock
{
    private $brandCode = null;
    private $model = [];
    private $fuelType = [];
    private $priceFrom = null;
    private $priceTo = null;

    /**
     * @var string
     */
    private $priceType = null;

    private $productionYear = [];
    private $gearboxType = [];
    private $driveType = [];
    private $enginePowerFrom = null;
    private $enginePowerTo = null;

    private $color = [];
    private $interiorType = [];
    private $equipmentCode = [];

    private $longitude = null;
    private $latitude = null;
    private $maxDistance = null;

    // TODO - wyszukiwanie po tagach ofert

    /**
     * @return array
     * @throws ApiException
     */
    public function getFilters()
    {
        $b = new Builder();

        $filters = [];

        if ($this->brandCode !== null) {
            $filters[] = $b->is(Fields::BRAND_CODE, '=', $this->brandCode);
        }
        
        if (count($this->model)) {
            $filters[] = $b->is(Fields::MODEL_COMMERCIAL_CODE, 'in', $this->model);
        }

        if (count($this->fuelType)) {
            $filters[] = $b->is(Fields::FUEL_TYPE, 'in', $this->fuelType);
        }

        if ($this->priceType == null and ($this->priceTo !== null or $this->priceFrom !== null)) {
            throw new ApiException('priceType cannot be null');
        } elseif ($this->priceTo !== null and $this->priceFrom === null) {
            $filters[] = $b->is($this->priceType, '<=', $this->priceTo);
        } elseif ($this->priceTo === null and $this->priceFrom !== null) {
            $filters[] = $b->is($this->priceType, '>=', $this->priceFrom);
        } elseif ($this->priceTo !== null and $this->priceFrom !== null) {
            $filters[] =
                $b->andWhere(
                    $b->is($this->priceType, '<=', $this->priceTo),
                    $b->is($this->priceType, '>=', $this->priceFrom)
                );
        }

        if (count($this->productionYear)) {
            $filters[] = $b->is(Fields::PRODUCTION_YEAR, 'in', $this->productionYear);
        }

        if (count($this->gearboxType)) {
            $filters[] = $b->is(Fields::GEARBOX_TYPE, 'in', $this->gearboxType);
        }

        if (count($this->driveType)) {
            $filters[] = $b->is(Fields::DRIVE_TYPE, 'in', $this->driveType);
        }

        if ($this->enginePowerTo !== null and $this->enginePowerFrom === null) {
            $filters[] = $b->is(Fields::ENGINE_POWER, '<=', $this->enginePowerTo);
        } elseif ($this->enginePowerTo === null and $this->enginePowerFrom !== null) {
            $filters[] = $b->is(Fields::ENGINE_POWER, '>=', $this->enginePowerFrom);
        } elseif ($this->enginePowerTo !== null and $this->enginePowerFrom !== null) {
            $filters[] =
                $b->andWhere(
                    $b->is(Fields::ENGINE_POWER, '<=', $this->enginePowerTo),
                    $b->is(Fields::ENGINE_POWER, '>=', $this->enginePowerFrom)
                );
        }
        
        if (count($this->color)) {
            $filters[] = $b->is(Fields::COLOR_CATEGORY, 'in', $this->color);
        }

        if (count($this->interiorType)) {
            $filters[] = $b->is(Fields::INTERIOR_TYPE, 'in', $this->interiorType);
        }

        if (count($this->equipmentCode)) {
            $filters[] = $b->is(Fields::EQUIPMENT_CODE, 'in', $this->equipmentCode);
        }

        if ($this->latitude !== null and $this->longitude !== null && $this->maxDistance !== null) {
            $filters[] = $b->isNear(Fields::DEALER_COORDINATES, $this->longitude, $this->latitude, $this->maxDistance);
        }

        return $b->andWhere(...$filters);
    }

    /**
     * @param $brandCode
     * @return $this
     */
    public function setBrandCode($brandCode)
    {
        $this->brandCode = $brandCode;
        return $this;
    }

    /**
     * @param $model
     * @return $this
     */
    public function setModel($model)
    {
        $this->model[] = (string) $model;
        return $this;
    }

    /**
     * @param $fuelType
     * @return $this
     */
    public function setFuelType($fuelType)
    {
        $this->fuelType[] = $fuelType;
        return $this;
    }

    /**
     * @param $priceFrom
     * @return $this
     */
    public function setPriceFrom($priceFrom)
    {
        $this->priceFrom = $priceFrom;
        return $this;
    }

    /**
     * @param $priceTo
     * @return $this
     */
    public function setPriceTo($priceTo)
    {
        $this->priceTo = $priceTo;
        return $this;
    }

    /**
     * @param $productionYear
     * @return $this
     */
    public function setProductionYear($productionYear)
    {
        $this->productionYear[] = $productionYear;
        return $this;
    }

    /**
     * @param $gearboxType
     * @return $this
     */
    public function setGearboxType($gearboxType)
    {
        $this->gearboxType[] = $gearboxType;
        return $this;
    }

    /**
     * @param $driveType
     * @return $this
     */
    public function setDriveType($driveType)
    {
        $this->driveType[] = $driveType;
        return $this;
    }

    /**
     * @param $enginePowerFrom
     * @return $this
     */
    public function setEnginePowerFrom($enginePowerFrom)
    {
        $this->enginePowerFrom = $enginePowerFrom;
        return $this;
    }

    /**
     * @param $enginePowerTo
     * @return $this
     */
    public function setEnginePowerTo($enginePowerTo)
    {
        $this->enginePowerTo = $enginePowerTo;
        return $this;
    }

    /**
     * @param $color
     * @return $this
     */
    public function setColor($color)
    {
        $this->color[] = $color;
        return $this;
    }

    /**
     * @param $interiorType
     * @return $this
     */
    public function setInteriorType($interiorType)
    {
        $this->interiorType[] = $interiorType;
        return $this;
    }

    /**
     * @param $equipmentCode
     * @return $this
     */
    public function setEquipmentCode($equipmentCode)
    {
        $this->equipmentCode[] = $equipmentCode;
        return $this;
    }

    /**
     * @param $priceType
     * @throws ApiException
     */
    public function setPriceType($priceType)
    {
        $validValues = [Fields::BASE_PRICE_BRUTTO, Fields::BASE_PRICE_NETTO, Fields::FINAL_PRICE_BRUTTO, Fields::FINAL_PRICE_NETTO];
        if (in_array($priceType, $validValues)) {
            $this->priceType = $priceType;
        } else {
            throw new ApiException('Invalid priceType value!');
        }
    }

    /**
     * @param $longitude double
     * @throws ApiException
     */
    public function setLongitude($longitude)
    {
        if (is_float($longitude)) {
            $this->longitude = $longitude;
        } else {
            throw new ApiException('Longitude must be double!');
        }
    }

    /**
     * @param $latitude double
     * @throws ApiException
     */
    public function setLatitude($latitude)
    {
        if (is_float($latitude)) {
            $this->latitude = $latitude;
        } else {
            throw new ApiException('Latitude must be double!');
        }
    }

    /**
     * @param $distance integer
     * @throws ApiException
     */
    public function setMaxDistance($distance)
    {
        if (is_int($distance)) {
            $this->maxDistance = $distance;
        } else {
            throw new ApiException('Max Distance must be integer!');
        }
    }
}
