<?php namespace Eae\Backoffice\Generic\Fields;

use LaravelLocalization;
use Config;
use View;
use RequestContext;
use Input;
use Lang;
use WebsiteObject;
use Eae\Backoffice\Generic\ContentType;
use Eae\Support\Contracts\SavableFieldInterface;
use ContentTypes;

class LinkField extends BaseField implements SavableFieldInterface
{

    protected $required = FALSE;
    protected $objectTypes = [];
    protected $maxLabel = 0;

    public function __construct($config)
    {
        unset($config["validation"]);
        unset($config["preValidation"]);
        unset($config["inList"]);
        unset($config["search"]);
        unset($config["sort"]);

        parent::__construct($config);

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

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

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

    public function isRequired()
    {
        return $this->required;
    }

    public function setRequired($required)
    {
        $this->required = $required;
    }

    public function toForm($model, $enabled = TRUE, $hidden = FALSE)
    {
        $html = "";

        $fieldName = $this->getName();
        $label = "";
        $isExternal = FALSE;
        $enabled = TRUE;
        $isExternal = FALSE;
        $selectedObjectId = NULL;
        $linkUrl = "";
        $linkLabel = "";

        $websiteModel = new WebsiteObject();
        $relation = $websiteModel->related();

        $query = WebsiteObject::with("objectable")
            ->whereIn("object_type", $this->getObjectTypesModelsType());

        $objects = $query->get();

        $fullList = [];

        foreach ($this->getContentTypes() as $contentType) {
            $fullList[ $contentType->getModelType() ] = [
                "label" => ucfirst($contentType->getLabel()),
                "list"  => []];
        }


        foreach ($objects as $object) {
            $fullList[ $object->object_type ]["list"][] = (object)[
                "id"    => $object->id,
                "title" => $object->objectable->title
            ];
        }

        foreach ($fullList as $listType) {
            usort($listType["list"], function ($firstItem, $secondItem) {
                if ($firstItem->title == $secondItem->title) {
                    return 0;
                }

                return ($firstItem->title < $secondItem->title) ? -1 : 1;
            });

        }

        $postData = Input::old($this->getName());

        $errors = RequestContext::get("errors");
        $hasErrors = FALSE;

        $html = "";
        if ($this->isMultiLanguage()) {
            $locales = LaravelLocalization::getSupportedLocales();
            $defaultLocale = LaravelLocalization::getDefaultLocale();

            foreach ($locales as $locale => $localeData) {
                $hasErrors = FALSE;
                $name = $fieldName . "[{$locale}]";
                $id = $fieldName . "_{$locale}";
                $errorKey = $fieldName . "." . $locale;
                $isExternal = FALSE;
                $selectedObjectId = NULL;
                $linkUrl = "";
                $linkLabel = "";

                if (!empty($errors) && !$errors->isEmpty()) {
                    if ($errors->has("{$this->getName()}.{$locale}.label") ||
                        $errors->has("{$this->getName()}.{$locale}.url") ||
                        $errors->has("{$this->getName()}.{$locale}.selectedObjectId")) {
                        $hasErrors = TRUE;
                    }
                }

                if ($model->exists) {
                    $languageModel = $model->languages->findByLocale($locale);

                    if (!empty($languageModel)) {
                        $value = $languageModel->$fieldName;
                    }

                    if (!empty($value)) {
                        $value = json_decode($value);
                        $linkLabel = $value->label;
                        $isExternal = $value->isExternal;
                        $linkUrl = $isExternal ? $value->url : NULL;
                        $selectedObjectId = !$isExternal ? $value->objectId : NULL;
                    }
                } else {
                    $isExternal = isset($postData[ $locale ]['isExternal']);
                }

                $html .= View::make(
                    "admin.generic.components.forms.link",
                    [
                        "id"           => $id,
                        "errorKey"     => $errorKey,
                        "hasErrors"    => $hasErrors,
                        "name"         => $name,
                        "label"        => $this->getLabel(),
                        "language"     => $locale,
                        "defaultLang"  => $defaultLocale,
                        "enabled"      => $enabled,
                        "parentHidden" => ($hidden && !empty($this->parent)),
                        "parent"       => $this->parent,
                        "required"     => $this->isRequired(),
                        "maxLength"    => 50,
                        "fullList"     => $fullList,
                        "hide"         => ($hidden || $locale != $defaultLocale),

                        "isExternal"       => $isExternal,
                        "linkLabel"        => $linkLabel,
                        "selectedObjectId" => $selectedObjectId,
                        "linkUrl"          => $linkUrl,
                        "info"             => $this->getInfo()
                    ]);
            }
        } else {
            if (!empty($errors) && !$errors->isEmpty()) {
                if ($errors->has("{$this->getName()}.label") ||
                    $errors->has("{$this->getName()}.url") ||
                    $errors->has("{$this->getName()}.selectedObjectId")) {
                    $hasErrors = TRUE;
                }
            }

            if ($model->exists) {
                $value = $model->$fieldName;

                if (!empty($value)) {
                    $value = json_decode($value);
                    $linkLabel = $value->label;
                    $isExternal = $value->isExternal;
                    $linkUrl = $isExternal ? $value->url : NULL;
                    $selectedObjectId = !$isExternal ? $value->objectId : NULL;
                }
            }

            $html .= View::make(
                "admin.generic.components.forms.link",
                [
                    "id"               => $this->getName(),
                    "errorKey"         => $this->getName(),
                    "hasErrors"        => $hasErrors,
                    "name"             => $this->getName(),
                    "label"            => $this->getLabel(),
                    "isExternal"       => $isExternal,
                    "enabled"          => $enabled,
                    "parentHidden"     => ($hidden && !empty($this->parent)),
                    "parent"           => $this->parent,
                    "required"         => $this->isRequired(),
                    "maxLength"        => 50,
                    "fullList"         => $fullList,
                    "isExternal"       => $isExternal,
                    "linkLabel"        => $linkLabel,
                    "selectedObjectId" => $selectedObjectId,
                    "linkUrl"          => $linkUrl,
                    "info"             => $this->getInfo()
                ]);
        }

        return $html;
    }

    public function save($model, $values)
    {
        $isExternal = isset($values['isExternal']) && $values['isExternal'] == 'true' ? TRUE : FALSE;
        $fieldStructure = [
            'label'      => $values['label'],
            'isExternal' => $isExternal,
            'url'        => $isExternal ? $values['url'] : NULL,
            'objectId'   => !$isExternal ? $values['selectedObjectId'] : NULL
        ];
        $fieldName = $this->getName();
        $model->$fieldName = json_encode($fieldStructure);
    }

    public function getValidation($subField = NULL)
    {
        $rules = "";
        if ($this->isRequired()) {
            $rules = "required|";
        }
        switch ($subField) {
            case 'label':
                if ($this->maxLabel > 0) {
                    $rules .= "max:{$this->maxLabel}";
                }
                break;
            case 'url':
                $rules .= "url";
                break;
            case 'selectedObjectId':
                $rules .= "integer";
                break;
        }

        return $rules;
    }

    public function getValidationData($copyAllLang = FALSE)
    {
        $validation = [
            "rules"  => [],
            "values" => [],
            "labels" => []];

        $fieldName = $this->getName();
        $fieldValue = Input::get($fieldName);

        if ($this->isMultiLanguage()) {
            foreach ($fieldValue as $lang => $langValue) {
                $fieldValue[ $lang ] = $langValue;
            }
        }

        if ($this->isMultiLanguage()) {
            $locales = LaravelLocalization::getSupportedLanguagesKeys();
            $defaultLocale = \Config::get('app.locale');
            if ($copyAllLang) {

                foreach ($locales as $locale) {
                    if ($locale == $defaultLocale) {
                        continue;
                    }

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


            $labelRules = generateLangRules(
                [$fieldName => $this->getValidation('label')],
                $locales,
                'label');

            $urlRules = [];
            foreach ($locales as $locale) {
                if (isset($value[ $locale ]['isExternal']) == 'true') {
                    $urlRules[ $fieldName . '.' . $locale . '.url' ] = $this->getValidation('url');
                } else {
                    $urlRules[ $fieldName . '.' . $locale . '.selectedObjectId' ] = $this->getValidation('selectedObjectId');
                }
            }
            $validation["rules"] = array_merge($labelRules, $urlRules);

            $labelLabel = generateLangLabels(
                $fieldName, Lang::get('backend.link_label'), $locales, 'label');
            $urlLabel = generateLangLabels(
                $fieldName, Lang::get('backend.link_url'), $locales, 'url');
            $isExternalLabel = generateLangLabels(
                $fieldName, Lang::get('backend.link_object'), $locales, 'selectedObjectId');
            $validation["labels"] = array_merge($labelLabel, $urlLabel, $isExternalLabel);
        } else {
            $validation["rules"][ $fieldName . '.label' ] = $this->getValidation('label');
            if (isset($value['isExternal']) == 'true') {
                $validation["rules"][ $fieldName . '.url' ] = $this->getValidation('url');
            } else {
                $validation["rules"][ $fieldName . '.selectedObjectId' ] = $this->getValidation('selectedObjectId');
            }
            $validation["labels"][ $fieldName . '.label' ] = Lang::get('backend.link_label');
            $validation["labels"][ $fieldName . '.url' ] = Lang::get('backend.link_url');
            $validation["labels"][ $fieldName . '.selectedObjectId' ] = Lang::get('backend.link_object');
        }

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

        return $validation;
    }

    public static function getScript()
    {
        return ["linkField" =>
                    Config::get('path.backoffice.js_path') . '/view/generic/backend-link-field.js'];
    }

    public function toArray()
    {
        $array = parent::toArray();
        $array["required"] = $this->required;

        return $array;
    }

    public function getObjectTypesModelsType()
    {
        $modelsType = [];
        foreach ($this->objectTypes as $objectType) {
            $contentType = ContentTypes::find($objectType);
            $modelsType[] = $contentType->getModelType();
        }

        return $modelsType;
    }

    public function getContentTypes()
    {
        $contentTypes = [];
        foreach ($this->objectTypes as $objectType) {
            $contentType = ContentTypes::find($objectType);
            $contentTypes[] = $contentType;
        }

        return $contentTypes;
    }

    public function setObjectTypes($objectTypes = [])
    {
        if (!empty($objectTypes)) {
            $this->websiteFiltered = TRUE;
        }

        $this->objectTypes = $objectTypes;
    }

    public function getObjectTypes()
    {
        return $this->objectTypes;
    }
}
  

