<?php

namespace App\Libs\Backoffice\Fields;

use App\Facades\Backoffice\BackendUserService;
use App\Facades\Backoffice\BackofficeService;
use App\Facades\Backoffice\ContentTypes;
use App\Libs\Backoffice\Contracts\SavableField;
use App\Libs\Backoffice\Exceptions\InvalidConfigurationException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Arr;

class RepeaterField extends BaseField
{
    protected $order = false;
    protected $objectType = false;
    protected $maxSize = false;

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

        parent::__construct($config);

        $this->relationField = true;

        if (empty($config["objectType"])) {
            throw new InvalidConfigurationException("The {$this->name} configuration is missing the object type");
        }

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

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

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

    public function isOrderable()
    {
        return $this->order;
    }

    public function setOrderable($order)
    {
        $this->order = $order;
    }

    public function getObjectType()
    {
        return $this->objectType;
    }

    public function getContentType()
    {
        return ContentTypes::find($this->objectType);
    }

    public function setObjectType($objectType)
    {
        $this->objectType = $objectType;
    }

    public function getMaxSize()
    {
        return $this->maxSize;
    }

    public function setMaxSize($maxSize)
    {
        $this->maxSize = $maxSize;
    }

    public function getData(Model $model, $enabled = true, $hidden = false)
    {
        $relationName = $this->getName();
        $relation = $model->$relationName();

        $contentType = $this->getContentType();
        $relationModelType = $contentType->getModelType();

        $relationModel = new $relationModelType;

        $languageRelationship = $relationModel->languages();
        $languageModel = $languageRelationship->getRelated();
        $websiteRelationship = $relationModel->websites();

        $websiteObjectModel = $websiteRelationship->getRelated();

        $query = $relationModel->full();

        if ($model->exists) {
            $query->where($relation->getQualifiedForeignKeyName(), $model->getKey());

            if ($this->isOrderable()) {
                $query->orderBy("{$websiteObjectModel->getTable()}.position", "asc");
            } else {
                $query->orderBy("{$languageModel->getTable()}.title", "asc");
            }

            $items = $query->get();
        } else {
            $items = [];
        }

        $contentData = [];
        foreach ($items as $item) {
            $itemData = $contentType->getData($item);
            $itemData['id'] = $item->id;
            $contentData[] = $itemData;
        }

        $value = [];

        return [
            'name' => $this->getName(),
            'type' => ucfirst($this->getType()),
            'label' => $this->getLabel(),
            'isOrderable' => $this->isOrderable(),
            'maxSize' => $this->getMaxSize(),
            'value' => $value,
            'hide' => $hidden,
            'enabled' => $enabled,
            'conditions' => $this->getConditions(),
            'info' => $this->getInfo(),
            'contentType' => $contentType->getType(),
            'itemsData' => $contentData,
            'contentTemplateData' => $contentType->getData($relationModel)
        ];
    }

    public function getValidationDataRules($model = null, $prefix = '')
    {
        $fieldName = $prefix . $this->getName();
        $fieldPrefix = "$fieldName.*.";
        $idField = $fieldPrefix . 'id';
        $rules = [
            $fieldName => 'array',
            $idField => 'integer|nullable'
        ];
        $labels = [];

        $contentType = $this->getContentType();
        foreach ($contentType->getFields() as $field) {
            $validation = $field->getValidationDataRules($model, $fieldPrefix);

            if (is_null($validation)) {
                continue;
            }

            $rules = array_merge($rules, $validation["rules"]);
            $labels = array_merge($labels, $validation["labels"]);
        }

        return [
            'rules' => $rules,
            'labels' => $labels
        ];
    }

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

        if (!$input) {
            $fieldValues = request(null)->input($fieldName);
        } else {
            $fieldValues = $input[$fieldName];
        }

        $processedValues = [];

        if (is_array($fieldValues)) {
            $contentType = $this->getContentType();

            foreach ($fieldValues as $fieldValue) {
                $itemValues = [];
                if (!empty($fieldValue['id'])) {
                    $itemValues['id'] = $fieldValue['id'];
                }

                foreach ($contentType->getFields() as $field) {
                    $itemValues[$field->getName()] = $field->getValidationDataValues($copyAllLang || empty($itemValues['id']), $fieldValue);
                }
                $processedValues[] = $itemValues;
            }
        }

        if (!$input) {
            request(null)->merge(array($fieldName => $processedValues));
        }

        return $processedValues;
    }

    /*
    public function getValidationData($copyAllLang = false)
    {
        $fieldName = $this->getName();
        $validation = $this->getValidationDataRules();

        $fieldValue = $this->getValidationDataValues($copyAllLang);

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

        return $validation;
    }
    */

    protected function prefixArrayKeys($array, $prefix) {
        foreach ($array as $k => $v){
            $array[$prefix . $k] = $v;
            unset($array[$k]);
        }
        return $array;
    }

    public function save(Model $model, $values)
    {
        $relationName = $this->getName();
        $contentType = $this->getContentType();
        $modelType = $contentType->getModelType();
        $parentData = $contentType->getParent();

        $existingIds = $model->$relationName()->get()->pluck('id')->toArray();

        $savedIds = [];

        foreach ($values as $idx => $contentData) {
            $repeaterModel = null;

            if (!empty($contentData['id'])) {
                $repeaterModel = $modelType::find($contentData['id']);
            }
            if (!$repeaterModel) {
                $repeaterModel = new $modelType;
            }

            $repeaterModel = BackofficeService::saveContentType(
                $contentType,
                $repeaterModel,
                $contentData,
                BackendUserService::getLoggedUser(),
                $parentData,
                $model->id
            );
            $websiteObject = $repeaterModel->getActiveWebsiteEntry();
            $websiteObject->position = $idx + 1;
            $websiteObject->save();
            $savedIds[] = $repeaterModel->id;
        }
        foreach (array_diff($existingIds, $savedIds) as $itemToDelete) {
            BackofficeService::deleteContentType($contentType, $itemToDelete);
        }
    }
}


