<?php

namespace App\Libs\Backoffice\Fields;

use App\Helpers\Backoffice\LanguageHelper;
use App\Libs\Backoffice\Exceptions\InvalidConfigurationException;
use App\Support\Backoffice\Sanitizer\Sanitizer;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Database\Eloquent\Model;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

abstract class BaseField implements Arrayable, Jsonable
{
    protected $label = "";
    protected $name;
    protected $multiLanguage = false;
    protected $preValidation = "";
    protected $validation = "";
    protected $inList = false;
    protected $search = false;
    protected $sort = false;
    protected $placement = "general";
    protected $relationField = false;
    protected $conditions = false;
    protected $disabled = false;
    protected $info = '';
    protected $state;
    protected $type;
    protected $listHeaderProps = [];
    protected $listField = 'title';

    public function __construct($config)
    {
        if (empty($config["name"])) {
            throw new InvalidConfigurationException("A field configuration is missing the name");
        }

        $this->name = $config["name"];

        if (!empty($config["label"])) {
            $this->label = $config["label"];
        }

        if (!empty($config["multiLanguage"])) {
            $this->multiLanguage = $config["multiLanguage"];
        }

        if (!empty($config["preValidation"])) {
            $this->preValidation = $config["preValidation"];
        }

        if (!empty($config["validation"])) {
            $this->validation = $config["validation"];
        }

        if (!empty($config["inList"])) {
            $this->inList = $config["inList"];
        }

        if (!empty($config["search"])) {
            $this->search = $config["search"];
        }

        if (!empty($config["sort"])) {
            $this->sort = $config["sort"];
        }

        if (!empty($config["placement"])) {
            $this->placement = strtolower($config["placement"]);
        }

        if (!empty($config["conditions"])) {
            $this->conditions = $config["conditions"];
        }

        if (!empty($config["disabled"])) {
            $this->disabled = $config["disabled"];
        }

        if (!empty($config["info"])) {
            $this->info = $config["info"];
        }

        if (!empty($config['listHeaderProps'])) {
            $this->listHeaderProps = $config['listHeaderProps'];
        }

        if (!empty($config["state"])) {
            if ($config["state"] === 'open' || $config["state"] === 'close') {
                $this->state = $config["state"];
            } else {
                throw new InvalidConfigurationException("A field has an invalid state value");
            }
        }

        if (!empty($config["type"])) {
            $this->type = $config["type"];
        }

        if (!empty($config["listField"])) {
            $this->listField = $config["listField"];
        }
    }

    public function setLabel($label)
    {
        $this->label = $label;
    }

    public function getLabel()
    {
        return trans($this->label);
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function isMultiLanguage()
    {
        return $this->multiLanguage;
    }

    public function setMultiLanguage($multiLanguage = false)
    {
        $this->multiLanguage = $multiLanguage;
    }

    public function setPreValidation($preValidation)
    {
        $this->preValidation = $preValidation;
    }

    public function getPreValidation()
    {
        return $this->preValidation;
    }

    public function setValidation($validation)
    {
        $this->validation = $validation;
    }

    public function getValidation()
    {
        return $this->validation;
    }

    public function getListField()
    {
        return $this->listField;
    }

    public function setListField($listField)
    {
        $this->listField = $listField;
    }

    public function isInList()
    {
        return $this->inList;
    }

    public function setInList($inList = false)
    {
        $this->inList = $inList;
    }

    public function isSearchable()
    {
        return $this->search;
    }

    public function setSearchable($search = false)
    {
        $this->search = $search;
    }

    public function isSortable()
    {
        return $this->sort;
    }

    public function setSortable($sort = false)
    {
        $this->sort = $sort;
    }

    public function setPlacement($placement)
    {
        $this->placement = $placement;
    }

    public function getPlacement()
    {
        return $this->placement;
    }

    public function isRelationField()
    {
        return $this->relationField;
    }

    public function setRelationField($relationField = false)
    {
        $this->relationField = $relationField;
    }

    public function isDisabled()
    {
        return $this->disabled;
    }

    public function setDisabled($disabled = false)
    {
        $this->disabled = $disabled;
    }

    public function getConditions()
    {
        return $this->conditions;
    }

    public function setConditions(array $conditions)
    {
        $this->conditions = $conditions;
    }

    public function setInfo($info)
    {
        $this->info = $info;
    }

    public function getInfo()
    {
        return $this->info;
    }

    public function getState()
    {
        return $this->state;
    }

    public function setState($state) {
        $this->state = $state;
    }

    public function getType()
    {
        return $this->type;
    }

    public function toForm(Model $model, $enabled = true, $hidden = false)
    {
        return "";
    }

    public function getData(Model $model, $enabled = true, $hidden = false)
    {
        return [];
    }

    public function getCurrentValue(Model $model)
    {
        $fieldName = $this->getName();

        if (request(null)->has($fieldName)) {
            return request(null)->input($fieldName);
        }

        if ($model->exists) {
            return $model->$fieldName;
        }

        return null;
    }

    public function getValidationDataValues($copyAllLang = false, $input = null)
    {
        $fieldName = $this->getName();

        if (!$input) {
            request(null)->merge(array($fieldName => $this->_preValidation(request(null)->input($fieldName))));
            $fieldValue = request(null)->input($fieldName);
        } else {
            $fieldValue = $this->_preValidation($input[$fieldName]);
        }

        if ($this->isMultiLanguage() && $copyAllLang) {
            $defaultLocale = LaravelLocalization::getDefaultLocale();
            $allLocales = LaravelLocalization::getSupportedLocales();

            foreach ($allLocales as $locale => $localeData) {
                if ($locale == $defaultLocale) {
                    continue;
                }

                if (empty($fieldValue[$locale])) {
                    $fieldValue[$locale] = $fieldValue[$defaultLocale];
                }
            }
        }

        return $fieldValue;
    }

    public function getValidationDataRules($model = null, $prefix = '')
    {
        $fieldName = $prefix . $this->getName();
        $validation = array(
            "rules" => array(),
            "labels" => array()
        );

        $rules = $this->getValidation();

        if (!empty($rules)) {
            if ($this->isMultiLanguage()) {
                $locales = LaravelLocalization::getSupportedLanguagesKeys();

                $validation["rules"] = LanguageHelper::generateLangRules(
                    array($fieldName => $rules),
                    $locales);

                $validation["labels"] = LanguageHelper::generateLangLabels(
                    $fieldName, $this->getLabel(), $locales);
            } else {
                $validation["labels"][$fieldName] = $this->getLabel();
                $validation["rules"][$fieldName] = $this->getValidation();
            }
        }

        return $validation;
    }

    protected function _preValidation($values)
    {
        $preValidation = $this->getPreValidation();

        if (empty($preValidation)) {
            return $values;
        }

        if ($this->isMultiLanguage()) {
            $filters = [];
            foreach (array_keys($values) as $language) {
                $filters[$language] = $preValidation;
            }

            $sanitizer = new Sanitizer($values, $filters);
            return $sanitizer->sanitize();

        } else {
            $filters = ['main' => $preValidation];
            $sanitizer = new Sanitizer(['main' => $values], $filters);
            $sanitizedData = $sanitizer->sanitize();
            return $sanitizedData['main'];
        }
    }

    public function toArray()
    {
        return array(
            "label" => $this->getLabel(),
            "name" => $this->name,
            "multiLanguage" => $this->isMultiLanguage(),
            "search" => $this->search,
            "sort" => $this->sort,
            "relationField" => $this->relationField,
            "conditions" => $this->conditions,
            "listHeaderProps" => $this->listHeaderProps
        );
    }

    public function toJson($options = 0)
    {
        return json_encode($this->toArray(), $options);
    }
}
