<?php

namespace App\Models\Backoffice\Support;

use App\Helpers\Backoffice\DatabaseHelper;
use App\Models\Backoffice\Support\Collections\ContentTypeCollection;
use App\Models\Backoffice\WebsiteObject;
use DateTime;
use Illuminate\Support\Arr;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

abstract class ContentTypeModel extends BaseModel
{
    protected $websiteAttributes = array(
        "website_object_id", "slug", "uri", "template", "status", "position", "content_type", "meta_title", "meta_description", "meta_image_id"
    );
    protected $related = array();

    public function websites()
    {
        return $this->morphMany(WebsiteObject::class, "objectable", "object_type", "object_id");
    }

    public function scopeFull($query)
    {
        $query->setEagerLoads([]);
        $languageRelation = $this->languages();
        $languageTable = $languageRelation->getRelated()->getTable();
        $languageFK = $languageRelation->getQualifiedForeignKeyName();
        $lang = LaravelLocalization::getCurrentLocale();
        $query->join($languageTable, function ($join) use ($languageTable, $languageFK, $lang) {
            $join->on("{$this->getTable()}.id", "=", "{$languageFK}")
                ->where("{$languageTable}.language_id", "=", $lang);
        });

        $websiteRelationship = $this->websites();
        $websiteObjectModel = $websiteRelationship->getRelated();
        $websiteObjectFK = $websiteRelationship->getQualifiedForeignKeyName();
        $model = $this;

        $query->join($websiteObjectModel->getTable(),
            function ($join) use ($model, $websiteObjectFK, $websiteRelationship) {
                $join->on($model->getQualifiedKeyName(), "=", $websiteObjectFK)
                    ->where($websiteRelationship->getMorphType(), "=", $model->getMorphClass());
            });

        $query->join('website_objects_lang',
            function ($join) use ($lang) {
                $join->on('website_objects_lang.website_object_id', "=", 'website_objects.website_object_id')
                    ->where('website_objects_lang.wo_language_id', "=", $lang);
            });

        return $query;
    }

    public function scopeNoWebsiteNoLang($query)
    {
        $query->setEagerLoads(array());
        return $query;
    }

    public function scopeWebsite($query)
    {
        $query->setEagerLoads(Arr::except($query->getEagerLoads(), "websites"));


        $websiteRelationship = $this->websites();
        $websiteObjectModel = $websiteRelationship->getRelated();
        $websiteObjectFK = $websiteRelationship->getQualifiedForeignKeyName();
        $model = $this;

        $query->join($websiteObjectModel->getTable(),
            function ($join) use ($model, $websiteObjectFK, $websiteRelationship) {
                $join->on($model->getQualifiedKeyName(), "=", $websiteObjectFK)
                    ->where($websiteRelationship->getMorphType(), "=", $model->getMorphClass());
            });

        return $query;

    }

    public function getAttribute($key)
    {

        if (parent::keyExists($key)) {
            return parent::getAttribute($key);
        }

        $inWebsiteAttributes = in_array($key, $this->websiteAttributes);
        if ($this->exists && $inWebsiteAttributes) {
            $websiteEntry = $this->getActiveWebsiteEntry();

            if (!empty($websiteEntry) && !empty($websiteEntry->$key)) {
                return $websiteEntry->$key;
            }


        }

        return null;
    }

    public function getActiveWebsiteEntry()
    {
        $websitesData = $this->websites;
        if (empty($websitesData)) {
            return null;
        }
        return $websitesData->first();
    }

    public function related($type, $order = "position", $withPerType = array())
    {
        if (isset($this->related[$type])) {
            return $this->related[$type];
        }

        $activeWebsite = $this->getActiveWebsiteEntry();

        if (empty($activeWebsite)) {
            $this->related[$type] = null;
            return $this->related[$type];
        }
        $query = $activeWebsite->related()->wherePivot("type", $type);
        if ($order == "position") {
            $query->orderBy("related.position", "asc");
        }

        $objects = $query->get();

        $objects->load("objectable");

        foreach ($withPerType as $objectType => $with) {
            DatabaseHelper::loadPolymorphicDependencies($objects, "objectable", $objectType, $with, "object_id", "object_type");
        }

        $objects = $objects->getObjectables();

        if ($order != "position") {
            $objects = $objects->sortBy(function ($model) {
                return $model->title;
            });
        }

        $this->related[$type] = $objects;
        return $this->related[$type];

    }

    public function setRelated($type, $collection)
    {
        $this->related[$type] = $collection;
    }

    public function toArray()
    {
        $array = parent::toArray();
        if (isset($this->relations["websites"])) {
            foreach ($this->websiteAttributes as $websiteAttribute) {
                if (!in_array($websiteAttribute, $this->hidden)) {
                    $array[$websiteAttribute] = $this->$websiteAttribute;
                    if ($array[$websiteAttribute] instanceof DateTime) {
                        $array[$websiteAttribute] = $array[$websiteAttribute]->format($this->getDateFormat());
                    }
                }
            }
        }
        return $array;
    }

    public function newCollection(array $models = array())
    {
        return new ContentTypeCollection($models);
    }

    public function keyExists($key)
    {
        return parent::keyExists($key) || in_array($key, $this->websiteAttributes);
    }


}
