<?php

namespace App\Libs\Backoffice\Generic\Fields;

use App\Libs\Contracts\Backoffice\SavableField;
use App\Libs\Contracts\Backoffice\SearchableField;
use App\Models\MediaItem;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class MediaPickerField extends BaseField implements SavableField, SearchableField
{
    protected $websiteFilter = false;
    protected $maxSize = false;
    protected $minSize = 0;
    protected $multiple = false;
    protected $thumbnailSizes = array();
    protected $relatedContentType = false;
    protected $mediaType = false;
    protected $allowed = false;
    protected $isFullscreen = false;

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

        parent::__construct($config);

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

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

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

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

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

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

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

        if ($this->multiple || $this->multiLanguage) {
            $this->relationField = true;
        }

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

    public function getMediaType()
    {
        return $this->mediaType;
    }

    public function setMediaType($mediaType)
    {
        $this->mediaType = $mediaType;
    }

    public function isMultiple()
    {
        return $this->multiple;
    }

    public function setMultiple($multiple)
    {
        $this->multiple = $multiple;
    }

    public function getAllowed()
    {
        return $this->allowed;
    }

    public function setAllowed($allowed)
    {
        $this->allowed = $allowed;
    }

    public function getIsFullscreen()
    {
        return $this->isFullscreen;
    }

    public function setIsFullscreen($isFullscreen)
    {
        $this->isFullscreen = $isFullscreen;
    }

    public function getValidation()
    {
        $rules = "array";
        if ($this->minSize > 0) {
            if ($this->parent) {
                $rules .= "|required_if:{$this->parent["name"]}," . implode(",", $this->parent["values"]);
                $parentValue = request()->input($this->parent["name"]);
                if (!is_null($parentValue) && in_array($parentValue, $this->parent["values"])) {
                    $rules .= "|min:" . $this->minSize;
                }
            } else {
                $rules .= "|required|min:" . $this->minSize;
            }
        }

        if ($this->maxSize > 0) {
            $rules .= "|max:" . $this->maxSize;
        }
        if (!empty($this->validation)) {
            $rules .= "|" . $this->validation;
        }
        if ($this->allowed) {
            $rules .= '|exists:media_items,id,extension,' . $this->allowed;
        }
        return $rules;
    }

    public function toForm(Model $model, $enabled = true, $hidden = false)
    {
        $fieldName = $this->getName();
        $mediaItems = [];
        $html = "";

        if ($this->isMultiLanguage()) {
            $locales = LaravelLocalization::getSupportedLocales();
            $defaultLocale = LaravelLocalization::getDefaultLocale();
            $postData = request()->old($this->getName());
            foreach ($locales as $locale => $localeData) {
                $name = $fieldName . "[{$locale}]";
                $id = $fieldName . "_{$locale}";
                $errorKey = $fieldName . "." . $locale;
                $value = null;
                $mediaItems = [];

                if (!empty($postData)) {
                    $ids = json_decode($postData[$locale]);
                    if (sizeof($ids) > 0) {
                        $idsString = implode(',', $ids);
                        $mediaItems = MediaItem::whereIn('id', $ids)
                            ->orderByRaw(DB::raw("FIELD(id, $idsString)"))
                            ->get();
                    }
                } else {
                    if ($model->exists) {
                        $relation = $model->$fieldName();
                        $query = $model->$fieldName()->wherePivot("language_id", $locale);
                        if ($this->multiple) {
                            $query->orderBy($model->$fieldName()->getTable() . '.position', 'asc');
                        }
                        $mediaItemsLangs = $query->get();
                        if (!$this->multiple) {
                            if (!$mediaItemsLangs->isEmpty()) {
                                $mediaItems[] = $mediaItemsLangs->first();
                            }
                        } else {
                            foreach ($mediaItemsLangs as $mediaItem) {
                                $mediaItems[] = $mediaItem;
                            }
                        }
                    }
                }

                $html .= view(
                    "admin.generic.components.forms.mediapicker",
                    array(
                        "id" => $id,
                        "name" => $name,
                        "errorKey" => $errorKey,
                        "label" => $this->getLabel(),
                        "mediaType" => $this->getMediaType(),
                        "mediaItems" => $mediaItems,
                        "multiple" => $this->multiple,
                        "minSize" => $this->minSize,
                        "maxSize" => $this->maxSize,
                        "isFullscreen" => $this->isFullscreen,
                        "language" => $locale,
                        "defaultLang" => $defaultLocale,
                        "hide" => ($hidden || $locale != $defaultLocale),
                        "enabled" => $enabled,
                        "relatedContentType" => $this->relatedContentType,
                        "parentHidden" => ($hidden && !empty($this->parent)),
                        "parent" => $this->parent,
                        "info" => $this->getInfo()
                    )
                );
            }
        } else {
            $postData = request()->old($this->getName());
            if (!empty($postData)) {
                $ids = json_decode($postData);
                if (sizeof($ids) > 0) {
                    $idsString = implode(',', $ids);
                    $mediaItems = MediaItem::whereIn('id', $ids)
                        ->orderByRaw(DB::raw("FIELD(id, $idsString)"))
                        ->get();
                }
            } else {
                if ($model->exists) {
                    if (!$this->multiple) {
                        if ($model->$fieldName) {
                            $mediaItems[] = $model->$fieldName;
                        }
                    } else {
                        $items = $model->$fieldName()->orderBy('position', 'asc')->get();
                        foreach ($items as $mediaItem) {
                            $mediaItems[] = $mediaItem;
                        }
                    }
                }
            }

            $html .= view(
                "admin.generic.components.forms.mediapicker",
                array(
                    "id" => $this->getName(),
                    "name" => $this->getName(),
                    "errorKey" => $this->getName(),
                    "label" => $this->getLabel(),
                    "mediaType" => $this->getMediaType(),
                    "mediaItems" => $mediaItems,
                    "multiple" => $this->multiple,
                    "minSize" => $this->minSize,
                    "maxSize" => $this->maxSize,
                    "isFullscreen" => $this->isFullscreen,
                    "hide" => $hidden,
                    "enabled" => $enabled,
                    "relatedContentType" => $this->relatedContentType,
                    "parentHidden" => ($hidden && !empty($this->parent)),
                    "parent" => $this->parent,
                    "info" => $this->getInfo()
                )
            );
        }
        return $html;
    }

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

        $fieldName = $this->getName();
        $value = request()->input($fieldName);
        if ($this->isMultiLanguage()) {
            foreach ($value as $lang => $langValue) {
                $value[$lang] = json_decode($langValue, true);
            }

            $defaultLocale = config('app.locale');
            $locales = LaravelLocalization::getSupportedLanguagesKeys();

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

                    if (empty($value[$locale])) {
                        $value[$locale] = $value[$defaultLocale];
                    }
                }
            }
        } else {
            $value = json_decode($value, true);
        }

        $rules = $this->getValidation();
        if (!empty($rules)) {
            if ($this->isMultiLanguage()) {
                $validation["rules"] = generateLangRules(
                    array($fieldName => $rules),
                    $locales
                );

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

    public function save(Model $model, $values)
    {
        if ($this->isMultiLanguage()) {
            $this->_saveMultipleLanguages($model, $values);
        } else {
            if ($this->isRelationField()) {
                $this->_saveSingleLanguage($model, $values);
            } else {
                $this->_saveSingle($model, $values);
            }
        }
    }

    protected function _saveSingle($model, $value)
    {
        $fieldName = $this->getName();
        $fkName = $model->$fieldName()->getForeignKeyName();
        $model->$fkName = empty($value) ? null : $value[0];
        /*if (!empty($value)) {
            $this->_generateThumbnails($value[0]);
        }*/
    }

    /*
    protected function _generateThumbnails($mediaItemId) {
        if (sizeof($this->thumbnailSizes) == 0) {
            return;
        }
        $mediaItem = MediaItem::find($mediaItemId);

        if (empty($mediaItem) || $mediaItem->media_type != MediaItem::MEDIA_TYPE_IMAGE) {
            return;
        }

        foreach ($this->thumbnailSizes as $size) {
            if (!isset($size["name"]) || !isset($size["width"]) || !isset($size["width"])) {
                throw new InvalidConfigurationException("All the sizes for generic backoffice fields of type 'image' must have a name, width and height in the configuration");
            }
            $destinationPath = Config::get('path.internal.thumbs');
            $fileName = $mediaItem->filename;
            $thumbFilename = getFileNameSize("{$destinationPath}/{$fileName}",$size["name"]);

            $originalImage = Config::get('path.internal.media') . '/' . $fileName;

            if (file_exists($thumbFilename)) {
                continue;
            }

            $quality = 90;
            if ($size["width"] > 1000) {
                $quality = 60;
            } else if ($size["width"] > 600) {
                $quality = 75;
            }

            switch($size["type"]){
                case "fit":
                    Image::make($originalImage)
                        ->fit($size["width"], $size["height"])
                        ->save($thumbFilename, $quality);
                    break;
                case "heighten":
                    Image::make($originalImage)
                        ->orientate()
                        ->heighten($size["height"])
                        ->save($thumbFileNamePath, $quality);
                    break;
                case "resize":
                    if(!isset($size["keepRatio"]) || $size["keepRatio"] === true){
                        Image::make($originalImage)
                            ->resize($size["width"], $size["height"], function ($constraint){
                                $constraint->aspectRatio();
                            })
                            ->resizeCanvas($size["width"], $size["height"])
                            ->save($thumbFilename, $quality);
                    }else{
                        Image::make($originalImage)
                            ->resize($size["width"], $size["height"])
                            ->save($thumbFilename, $quality);
                    }
                    break;
                default:
                    throw new InvalidConfigurationException("The types allowed for for generic backoffice fields of type 'image' are fit or resize in the configuration");
            }
        }
    }
    */
    protected function _saveMultipleLanguages($model, $values)
    {
        $relationName = $this->getName();

        $locales = LaravelLocalization::getSupportedLocales();
        foreach ($locales as $locale => $localeData) {
            $langValues = $values[$locale];
            $syncData = array();
            $position = 1;

            foreach ($langValues as $id) {
                $syncData[$id] = array("language_id" => $locale);

                if ($this->isMultiple()) {
                    $syncData[$id]["position"] = $position;
                    $position = $position + 1;
                }

                //$this->_generateThumbnails($id);
            }

            $model->$relationName()->wherePivot("language_id", $locale)->sync($syncData);
        }
    }

    protected function _saveSingleLanguage($model, $values)
    {
        $relationName = $this->getName();

        $syncData = array();
        $position = 1;
        foreach ($values as $id) {
            $syncData[$id] = array("position" => $position);
            $position = $position + 1;

            //$this->_generateThumbnails($id);
        }
        $model->$relationName()->sync($syncData);
    }

    public function getSearchStructure(Model $model, $view = false)
    {
        $searchData = array();

        if ($this->isMultiLanguage() || $this->isRelationField()) {
            return $searchData;
        }

        $fieldName = $this->getName();
        $fkName = $model->$fieldName()->getForeignKeyName();

        if (!empty($model->$fkName)) {
            $languages = LaravelLocalization::getSupportedLocales();

            foreach ($languages as $language) {

                $searchData[$language] = $model->$fkName;
            }
        }

        return $searchData;
    }

    public function toArray()
    {
        $array = parent::toArray();
        //$array["maxSize"] = $this->maxSize;
        //$array["minSize"] = $this->minSize;
        return $array;
    }

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