<?php

namespace App\Libs\Backoffice\Generic\Fields;

use App\Libs\Exception\InvalidConfigurationException;
use App\Libs\Security\XSSCleanFilter;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Database\Eloquent\Model;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Waavi\Sanitizer\Sanitizer;

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 = "main";
    protected $relationField = false;
    protected $parent = false;
    protected $disabled = false;
    protected $info = false;

    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 = $config["placement"];
        }

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

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

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

    }

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

    public function getLabel()
    {
        return $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 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 getParent()
    {
        return $this->parent;
    }

    public function setParent($fieldName, $values)
    {
        $this->parent = array("name" => $fieldName, "values" => $values);
    }

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

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

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

    public function getCurrentValue(Model $model)
    {
        $fieldName = $this->getName();
        if (request()->has($fieldName)) {
            return request()->input($fieldName);
        }

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

        return null;
    }

    public function getValidationData($copyAllLang = false)
    {
        $validation = array(
            "rules" => array(),
            "values" => array(),
            "labels" => array()
        );

        $rules = $this->getValidation();
        $fieldName = $this->getName();
        request()->merge(array($fieldName => $this->_preValidation(request()->input($fieldName))));
        $fieldValue = request()->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];
                }
            }

        }

        $validation["values"][$fieldName] = $fieldValue;

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

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

                $validation["labels"] = 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;
        }

        $customFilters = [
            'xss_clean' => XSSCleanFilter::class
        ];

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

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

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

        return $values;
    }

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

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

    public static function getScript()
    {
        return array(
            "genericField" =>
                path_asset('path.backoffice.js_path').'/view/generic/backend-generic-field.js'
        );

    }

}