<?php

namespace App\Libs\Backoffice\Generic\Fields;


use App\Libs\Exception\InvalidConfigurationException;
use App\Libs\Facades\Localization;
use App\Libs\Support\Sanitizer\Sanitizer;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;

class BaseField implements Arrayable, Jsonable
{
    protected $label = "";
    protected $name;
    protected $multiLanguage = false;
    protected $preValidation = "";
    protected $blocksMode = false;
    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;
    protected $websites = false;
    protected $contentType = null;

    public function __construct($config, $contentType = null)
    {
        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["blocksMode"])) {
            $this->blocksMode = $config["blocksMode"];
        }

        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"];
        }

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

        $this->contentType = $contentType;
    }

    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 setBlocksMode($blocksMode)
    {
        $this->blocksMode = $blocksMode;
    }

    public function getBlocksMode()
    {
        return $this->blocksMode;
    }

    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, $enabled = true, $hidden = false)
    {
        return "";
    }

    public function getCurrentValue($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 = Localization::getDefaultLocale();
            $allLanguages = Localization::getAllLanguages();
            if (!array_key_exists($defaultLocale, $fieldValue)) {
                throw new InvalidConfigurationException("The current website doesn't have the backoffice default language");
            }

            foreach ($allLanguages as $languages) {
                $locale = $languages->id;
                if ($locale == $defaultLocale) {
                    continue;
                }

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

        }

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

        if (!empty($rules)) {
            if ($this->isMultiLanguage()) {
                $languages = Localization::getSupportedLanguages();

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

                $validation["labels"] = generateLangLabels(
                    $fieldName, $this->getLabel(), $languages);
            } 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'];
        }

        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/backend-generic-field.js'
        );

    }

    public function loadVersion($model, $fields, $langFields)
    {
        $fieldName = $this->getName();
        if ($this->isMultiLanguage()) {
            if (array_key_exists($fieldName, $langFields)) {
                foreach ($model->languages as $languageModel) {
                    if (array_key_exists($languageModel->language_id, $langFields[$fieldName])) {
                        $languageModel->$fieldName = $langFields[$fieldName][$languageModel->language_id];
                    }
                }
            }
        } else {
            if (isset($fields[$fieldName])) {
                $model->$fieldName = $fields[$fieldName];
            }
        }
    }

    public function getVersionStructure($model)
    {
        $fieldVersion = array();
        $fieldName = $this->getName();

        if ($this->isMultiLanguage()) {
            $fieldVersion['multilanguage'] = true;
            $fieldVersion['value'] = array();
            foreach ($model->languages as $languageModel) {
                $value = $languageModel->$fieldName;
                $fieldVersion['value'][$languageModel->language_id] = $languageModel->$fieldName;
            }
        } else {
            $fieldVersion['multilanguage'] = false;
            $fieldVersion['value'] = $model->$fieldName;
        }

        return $fieldVersion;
    }

    public function websiteVisible($websiteId)
    {
        if ($this->websites === false) {
            return true;
        }
        return in_array($websiteId, $this->websites);
    }

    public function isVersionable()
    {
        return true;
    }

    public function duplicate($sourceModel, $model)
    {
        $fieldName = $this->getName();

        if ($this->isMultiLanguage()) {
            $languages = Localization::getSupportedLanguages();
            foreach ($languages as $language) {
                $sourceModelLang = $sourceModel->languages->findByLocale($language->id);
                $modelLang = $model->languages->findByLocale($language->id);
                $modelLang->$fieldName = $sourceModelLang->$fieldName;
            }
        } else {
            $model->$fieldName = $sourceModel->$fieldName;
        }
    }
}
