<?php

namespace App\Libs\Backoffice\Generic;

use App\Facades\RequestContext;
use App\Facades\Services\BackendUserService;
use App\Libs\Backoffice\Generic\Actions\BaseAction;
use App\Libs\Backoffice\Generic\Fields\SelectBoxField;
use App\Libs\Backoffice\Generic\Fields\TextBoxField;
use App\Libs\Contracts\Backoffice\ExternalField;
use App\Libs\Contracts\Backoffice\ListableField;
use App\Libs\Contracts\Backoffice\SearchableField;
use App\Libs\Exception\InvalidConfigurationException;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class ContentType implements Arrayable, Jsonable
{
    const SHAREABLE_NONE = "none";
    const SHAREABLE_SHARE = "share";
    const SHAREABLE_GLOBAL = "global";

    protected $type;
    protected $group;
    protected $modelType;
    protected $label = "";
    protected $labelSingular = "";
    protected $template = false;
    protected $templates = false;
    protected $hierarchic = false;
    protected $order = false;
    protected $showSlug = false;
    protected $showStatus = false;
    protected $showUri = false;
    protected $hasStatus = true;
    protected $fields;
    protected $actions;
    protected $baseUri = false;
    protected $parent = false;
    protected $search = [];
    protected $showId = false;
    protected $filters;
    protected $hasUri = false;

    public function __construct($config)
    {
        if (empty($config)) {
            throw new InvalidConfigurationException("You must provide a configuration");
        }

        if (is_string($config)) {
            $config = config("backoffice.generic.{$config}");
        }

        if (empty($config) || !is_array($config)) {
            throw new InvalidConfigurationException("You must provide a configuration");
        }

        $this->_initialize($config);
    }

    protected function _initialize($config)
    {
        if (empty($config["type"])) {
            throw new InvalidConfigurationException("The configuration is missing type");
        }

        if (empty($config["model"]) || !class_exists($config["model"])) {
            throw new InvalidConfigurationException("The configuration is missing a valid model");
        }

        if (empty($config["fields"])) {
            throw new InvalidConfigurationException("The configuration is missing fields");
        }

        $backendUser = BackendUserService::getLoggedUser();

        if (!empty($backendUser)) {
            if (!$backendUser->hasPermission("cms.manage")) {
                throw new InvalidPermissionException("You don't have permissions to view this content type");
            }
        }

        $this->modelType = $config["model"];
        $this->type = $config["type"];
        $this->label = $config["label"];
        $this->labelSingular = $config["label_singular"];

        if (empty($config["group"])) {
            $this->group = trans('backend.content');
        } else {
            $this->group = $config["group"];
        }
        if (!empty($config["search"])) {
            $this->search = $config["search"];
        }

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

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

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

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

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

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

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

        if (isset($config["hasStatus"])) {
            $this->hasStatus = $config["hasStatus"];
        }

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

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

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

        if (array_key_exists('hasUri', $config)) {
            $this->hasUri = $config["hasUri"];
        }

        $this->fields = new FieldCollection();
        $this->actions = new ActionCollection();

        if (!empty($config["actions"]) && !empty($backendUser)) {
            foreach ($config["actions"] as $action) {
                $actionType = ucfirst($action);
                $class = "App\\Libs\\Backoffice\\Generic\\Actions\\{$actionType}Action";
                $class = new $class();
                $this->actions->push(new $class());
            }
        }

        $sectionCount = 0;

        foreach ($config["fields"] as $fieldConfig) {
            if (empty($fieldConfig["type"])) {
                throw new InvalidConfigurationException("There are fields without a type in the configuration");
            }if ($fieldConfig["type"] === 'section') {
                $sectionCount++;
            }
            $fieldType = ucfirst($fieldConfig["type"]);
            $class = "App\\Libs\\Backoffice\\Generic\\Fields\\{$fieldType}Field";
            $this->fields->push(new $class($fieldConfig,  $this->getModelType()));
        }
        if ($sectionCount % 2) {
            throw new InvalidConfigurationException("There are section fields with invalid matching types");
        }
    }

    public function getType()
    {
        return $this->type;
    }

    public function setType($type)
    {
        $this->type = $type;
    }

    public function getHasUri()
    {
        return $this->hasUri;
    }

    public function setHasUri($hasUri)
    {
        $this->hasUri = $hasUri;
    }

    public function getModelType()
    {
        return $this->modelType;
    }

    public function setModelType($modelType)
    {
        $this->modelType = $modelType;
    }

    public function getLabel()
    {
        return $this->label;
    }

    public function setLabel($label)
    {
        $this->label = $label;
    }

    public function getSingularLabel()
    {
        return $this->labelSingular;
    }

    public function setSingularLabel($labelSingular)
    {
        $this->labelSingular = $labelSingular;
    }

    public function getFields()
    {
        return $this->fields;
    }

    public function isHierarchic()
    {
        return $this->hierarchic;
    }

    public function setHierarchic($hierarchic = false)
    {
        $this->hierarchic = $hierarchic;
    }

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

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

    public function getShowSlug()
    {
        return $this->showSlug;
    }

    public function setShowSlug($showSlug = false)
    {
        $this->showSlug = $showSlug;
    }

    public function getShowStatus()
    {
        return $this->showStatus;
    }

    public function setShowStatus($showStatus = false)
    {
        $this->showStatus = $showStatus;
    }

    public function getShowUri()
    {
        return $this->showUri;
    }

    public function setHasStatus($hasStatus = true)
    {
        $this->hasStatus = $hasStatus;
    }

    public function getHasStatus()
    {
        return $this->hasStatus;
    }

    public function getShowId()
    {
        return $this->showId;
    }

    public function setShowUri($showUri = false)
    {
        $this->showUri = $showUri;
    }

    public function hasTemplate()
    {
        return $this->template;
    }

    public function setTemplate($template = false)
    {
        $this->template = $template;
    }

    public function getTemplates()
    {
        return $this->templates;
    }

    public function getActions($actionType = null)
    {
        if (empty($actionType)) {
            return $this->actions;
        } else {
            return $this->actions->getActionsByActionType($actionType);
        }
    }

    public function hasActions($actionType = null)
    {
        $actions = $this->getActions($actionType);
        return !$actions->isEmpty();
    }

    public function getGroup()
    {
        return $this->group;
    }

    public function setGroup($group)
    {
        if (empty($group)) {
            $this->group = trans('backend.content');
        } else {
            $this->group = $group;
        }
    }

    public function getBaseUri()
    {
        return $this->baseUri;
    }

    public function setBaseUri($baseUri)
    {
        $this->baseUri = $baseUri;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function setParent($parent)
    {
        $this->parent = $parent;
    }

    public function getFilters()
    {
        return $this->filters;
    }

    public function setFilters($filters)
    {
        $this->filters = $filters;
    }

    public function isSearchable()
    {
        return $this->search;
    }

    public function getSearch()
    {
        return $this->search;
    }

    public function getSearchFields()
    {
        return array_key_exists('fields', $this->search) ? $this->search['fields'] : null;
    }

    public function getSearchParentRelationships()
    {
        return array_key_exists('parentRelationships', $this->search) ? $this->search['parentRelationships'] : null;
    }

    public function getSearchRelations()
    {
        return array_key_exists('relations', $this->search) ? $this->search['relations'] : null;
    }

    public function getSearchIncludes()
    {
        return array_key_exists('include', $this->search) ? $this->search['include'] : null;
    }

    public function getSearchTitle()
    {
        return array_key_exists('title', $this->search) ? $this->search['title'] : null;
    }

    public function toList($page = null, $itemsPerPage = null, $sort = null, $searchPhrase = null)
    {

        if ($this->isHierarchic()) {
            if (empty($sort) && empty($searchPhrase)) {
                return $this->_toHierarchicList($page, $itemsPerPage);
            }
        }

        return $this->_toFlatList($page, $itemsPerPage, $sort, $searchPhrase);
    }

    public function toStructuredList()
    {
        $items = $this->_toHierarchicList(null, null);
        $list = array();

        foreach ($items as $item) {
            $list[$item->id] = $item;
        }
        return $this->_structureList($list);
    }

    private function _structureList($listItems, $root = null)
    {
        $return = array();
        foreach ($listItems as $id => $item) {
            if ($item->getActiveWebsiteEntry()->parent_id == $root) {
                unset($listItems[$id]);
                $item->children = $this->_structureList($listItems, $item->getActiveWebsiteEntry()->id);
                $return[] = $item;
            }
        }
        return $return;
    }

    protected function _toFlatList($page, $itemsPerPage, $sort, $searchPhrase)
    {
        Paginator::currentPageResolver(function () use ($page) {
            return $page;
        });

        $fields = $this->fields->getListableFields();
        $hasLanguage = !$fields->getMultiLanguageFields()->isEmpty();

        $sortColumn = null;
        $orderField = null;
        $sortOrder = null;
        if (!empty($sort)) {
            $sortColumn = head(array_keys($sort));
            $sortOrder = $sort[$sortColumn];
            $sortColumn = str_replace("relation.", "", $sortColumn);
            if ($sortColumn != "slug" && $sortColumn != "uri" && $sortColumn != "status" && $sortColumn != "position") {
                $orderField = $fields->find($sortColumn);

                if (empty($orderField)) {
                    throw new InvalidConfigurationException("The order field is not part of this content type list fields");
                }
            }
        }

        $modelType = $this->modelType;

        $queryBuilder = $modelType::query();
        $model = $queryBuilder->getModel();

        $websiteEntryRelationship = $model->websites();
        $websiteEntryModel = $websiteEntryRelationship->getRelated();
        $websiteEntryFK = $websiteEntryRelationship->getQualifiedForeignKeyName();

        $queryBuilder->join($websiteEntryModel->getTable(),
            function ($join) use ($model, $websiteEntryFK, $websiteEntryRelationship, $modelType) {
                $join->on($model->getQualifiedKeyName(), "=", $websiteEntryFK)
                    ->where($websiteEntryRelationship->getMorphType(), "=", $modelType);
            });

        if ($hasLanguage) {
            $languageRelationship = $model->languages();
            $languageModel = $languageRelationship->getRelated();
            $languageFK = $languageRelationship->getQualifiedForeignKeyName();
            $queryBuilder->join($languageModel->getTable(), $model->getQualifiedKeyName(), "=", $languageFK);
            $queryBuilder->where("{$languageModel->getTable()}.language_id", "=",
                LaravelLocalization::getCurrentLocale());
        }
        if (!empty($sortColumn)) {

            if (!empty($orderField)) {
                $orderField->buildOrder($queryBuilder, $sortOrder);
            } else {
                $queryBuilder->orderBy("{$websiteEntryModel->getTable()}.{$sortColumn}", $sortOrder);
            }
        }

        foreach ($this->getFilters() as $filter) {
            if (is_null($filter["value"])) {
                $queryBuilder->whereNull($filter["field"]);
            } else {
                $queryBuilder->where($filter["field"], $filter["value"]);
            }
        }

        $queryBuilder->addSelect($model->getQualifiedKeyName());

        if ($this->getShowUri()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".uri");
        }

        if ($this->getShowSlug()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".slug");
        }

        if ($this->getShowStatus()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".status");
        }

        foreach ($fields as $field) {
            if ($field instanceof ListableField) {
                $field->buildSelect($queryBuilder);
            }
        }
        if (!empty($searchPhrase)) {
            $queryBuilder->where(function ($query) use ($fields, $searchPhrase) {
                foreach ($fields as $field) {
                    if ($field instanceof ListableField) {
                        $field->buildWhere($query, $searchPhrase);
                    }
                }
            });
            if (is_numeric($searchPhrase)) {
                $table = $queryBuilder->getModel()->getTable();
                $langTable = $queryBuilder->getModel()->languages()->getRelated()->getTable();
                $queryBuilder->orWhere("{$table}.id", $searchPhrase * 1);
                $queryBuilder->where("$langTable.language_id", LaravelLocalization::getCurrentLocale());
            }
        }

        if (empty($page) || empty($itemsPerPage)) {
            $rows = $queryBuilder->get();
            return $rows;
        } else {
            $paginator = $queryBuilder->paginate($itemsPerPage);

            return array(
                "total" => $paginator->total(),
                "current" => $paginator->currentPage(),
                "rowCount" => $itemsPerPage,
                "rows" => $paginator->getCollection()
            );
        }
    }

    protected function _toHierarchicList($page, $itemsPerPage)
    {

        $fields = $this->fields->getListableFields();

        if (!$this->isOrderable()) {
            $hasLanguage = true;
        } else {
            $hasLanguage = !$fields->getMultiLanguageFields()->isEmpty();
        }

        $modelType = $this->modelType;

        $queryBuilder = $modelType::query();
        $model = $queryBuilder->getModel();

        $websiteEntryRelationship = $model->websites();


        $websiteEntryModel = $websiteEntryRelationship->getRelated();
        $websiteEntryFK = $websiteEntryRelationship->getQualifiedForeignKeyName();


        $queryBuilder->join($websiteEntryModel->getTable(),
            function ($join) use ($model, $websiteEntryFK, $websiteEntryRelationship, $modelType) {
                $join->on($model->getQualifiedKeyName(), "=", $websiteEntryFK)
                    ->where($websiteEntryRelationship->getMorphType(), "=", $modelType);
            });

        if ($hasLanguage) {
            $languageRelationship = $model->languages();
            $languageModel = $languageRelationship->getRelated();
            $languageFK = $languageRelationship->getQualifiedForeignKeyName();
            $queryBuilder->join($languageModel->getTable(), $model->getQualifiedKeyName(), "=", $languageFK);
            $queryBuilder->where("{$languageModel->getTable()}.language_id", "=",
                LaravelLocalization::getCurrentLocale());
        }

        $queryBuilder->orderBy("{$websiteEntryModel->getTable()}.parent_id", "asc");

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

        $queryBuilder->addSelect($model->getQualifiedKeyName());
        $queryBuilder->addSelect($websiteEntryModel->getTable().".parent_id");
        $queryBuilder->addSelect($websiteEntryModel->getTable().".template");

        if ($this->getShowUri()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".uri");
        }

        if ($this->getShowSlug()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".slug");
        }

        if ($this->getShowStatus()) {
            $queryBuilder->addSelect($websiteEntryModel->getTable().".status");
        }

        foreach ($fields as $field) {
            if ($field instanceof ListableField) {
                $field->buildSelect($queryBuilder);
            }
        }

        $rows = $queryBuilder->get();
        $rows = new EloquentCollection($this->_buildHierarchicList($rows));

        if (empty($page) || empty($itemsPerPage)) {
            return $rows;
        } else {
            $offset = ($page - 1) * $itemsPerPage;

            return array(
                "total" => $rows->count(),
                "current" => (int) $page,
                "rowCount" => (int) $itemsPerPage,
                "rows" => $rows->slice($offset, $itemsPerPage)->values()
            );
        }

    }

    protected function _buildHierarchicList(
        EloquentCollection $oriItems,
        array $outItems = array(),
        $parent_id = null,
        $depth = 0
    ) {

        foreach ($oriItems as $item) {
            if ($item->getActiveWebsiteEntry()->parent_id == $parent_id) {
                $titlePrefix = "";
                for ($i = 0; $i < $depth; $i++) {
                    $titlePrefix .= "— ";
                }
                $item->clean_title = $item->title;
                $item->title = $titlePrefix.$item->title;
                array_push($outItems, $item);
                $outItems = $this->_buildHierarchicList($oriItems, $outItems, $item->getActiveWebsiteEntry()->id,
                    $depth + 1);
            } elseif ($item->getActiveWebsiteEntry()->parent_id > $parent_id) {
                break;
            }
        }

        return $outItems;
    }

    public function hasFormFields()
    {
        $fields = $this->fields->getMainFormFields();
        return !$fields->isEmpty();
    }

    public function toForm($model, $placement = "main", $isPreview = FALSE)
    {
        $fields = $this->fields->getFieldsByPlacement($placement);
        $form = "";
        $enabled = $this->userHasPermission() && !$isPreview;
        foreach ($fields as $field) {
            if ($field instanceOf ExternalField) {
                continue;
            }
            $parent = $field->getParent();
            $hidden = false;
            if (!empty($parent)) {
                $value = $this->getFieldValue($parent["name"], $model);
                if (!in_array($value, $parent["values"])) {
                    $hidden = true;
                }
            }
            $form .= $field->toForm($model, $enabled, $hidden);
        }
        return $form;
    }

    public function toExternalForm($model, $placement = "main", $isPreview = FALSE)
    {
        $fields = $this->fields->getExternalFields($placement);
        $form = "";
        $enabled = $this->userHasPermission() && !$isPreview;
        foreach ($fields as $field) {
            $parent = $field->getParent();
            $hidden = false;
            if (!empty($parent)) {
                $value = $this->getFieldValue($parent["name"], $model);
                if (!in_array($value, $parent["values"])) {
                    $hidden = true;
                }
            }
            $form .= $field->toForm($model, $enabled, $hidden);
        }
        return $form;
    }

    public function getFieldValue($fieldName, $model)
    {
        $field = $this->fields->find($fieldName);
        if (!is_null($field)) {
            return $field->getCurrentValue($model);
        } else {
            //this if the field is the slug or template
            return $model->$fieldName;
        }

    }

    public function toWebsiteForm($model, $placement = 'main', $isPreview = FALSE)
    {
        $form = "";
        $enabled = $this->userHasPermission() && !$isPreview;
        $slug = new TextBoxField(array(
            "name" => 'lang_slug', 'label' => 'slug',
            'multiLanguage' => true, 'woMultilang' => true
        ));
        $slugInput = request()->old("slug");
        $hidden = false;
        if (!$model->exists && empty($slugInput)) {
            $hidden = true;
        }

        $form .= $slug->toForm($model, $enabled, $hidden);
        $status = new SelectBoxField(array(
            "name" => 'status',
            'label' => 'status',
            "list" => array(
                "draft" => trans("backend.draft"),
                "published" => trans("backend.published")
            ),
            "defaultValue" => "published"
        ), $this->getModelType());

        $form .= $status->toForm($model, $enabled, !$this->hasStatus);

        if ($this->template) {
            $templatesSelectList = array();
            $templates = array();

            if (!empty($this->templates)) {
                $templates = $this->templates;
            }

            foreach ($templates as $template) {
                $templatesSelectList[$template['id']] = $template['name'];
            }

            $defaultValue = "";
            /*if (!empty($templates)) {
                $defaultValue = head($templates)['id'];
            }*/

            $templateSelect = new SelectBoxField(array(
                "name" => "template",
                "label" => "template",
                "list" => $templatesSelectList,
                "defaultValue" => $defaultValue
            ), $this->getModelType());
            $form .= $templateSelect->toForm($model, $enabled);
        }
        if ($model->exists && ($this->baseUri || $this->hasTemplate()) && $enabled) {
            $form .= '<a href="#" data-uri="'.$model->uri
                .'" target="_blank" class="preview-page btn btn-primary pull-right">Preview</a><div class="clearfix"></div>';
        }

        return $form;
    }

    public function getValidation($copyDefaultLang = false)
    {
        $rules = array();
        $values = array();
        $labels = array();
        foreach ($this->fields as $field) {
            $validation = $field->getValidationData($copyDefaultLang);

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

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

        $languages = array_keys(getAvailableLanguages());
        foreach ($languages as $langCode) {
            $rules["lang_slug.{$langCode}"] = "required";
        }
        $rules['status'] = "required|in:draft,published";

        if ($this->template) {
            $templates = $this->getTemplates();
            $availTemplates = implode(',', array_keys($templates));
            $rules['template'] = "required|in:".$availTemplates;
        }

        $values['lang_slug'] = request()->input("lang_slug");
        $values['status'] = request()->input("status");
        $values['template'] = request()->input("template");
        $labels['slug'] = "slug";
        $labels['status'] = "status";
        $labels['template'] = "template";

        return array("rules" => $rules, "values" => $values, "labels" => $labels);
    }

    public function getErrorLocales()
    {
        $errorLocales = array();
        $errors = RequestContext::get('errors');
        if (empty($errors)) {
            return $errorLocales;
        }

        $locales = LaravelLocalization::getSupportedLocales();

        foreach ($locales as $locale => $localeData) {
            $errorLanguage = Arr::where($errors->toArray(), function ($value, $key) use ($locale) {
                return Str::endsWith($key, ".".$locale) || Str::contains($key, ".{$locale}.");
            });

            if (!empty($errorLanguage)) {
                $errorLocales[] = $locale;
            }
        }
        return $errorLocales;

    }

    /*
    public function getScripts(){
        $scripts = array(
            'genericForm' => path_asset('path.backoffice.js_path') . '/view/backend-generic-form.js',
            'langPicker' => path_asset('path.backoffice.js_path') . '/view/backend-lang-tab-picker.js'
        );

        foreach($this->fields as $field){
            $script = $field->getScript();
            if(!is_null($script)){
                $scripts = array_merge($scripts, $script);
            }
        }

        return $scripts;
    }
    */

    public function hasExternalFields()
    {
        $externalFields = $this->fields->getExternalFields();
        if ($externalFields->isEmpty()) {
            return false;
        } else {
            return true;
        }
    }

    public function userHasPermission()
    {
        $user = BackendUserService::getLoggedUser();
        if (empty($user)) {
            return false;
        }

        return $user->hasPermission("cms.manage");
    }

    public function getSearchStructure($model)
    {
        if (!$this->isSearchable()) {
            return array();
        }

        $search = array();
        $searchData = $this->getSearch();

        $searchLevels = array("primary", "secondary");


        foreach ($searchLevels as $level) {
            if (!empty($searchData[$level])) {
                $searchFields = $this->fields->getFieldsByNames($searchData[$level]);

                foreach ($searchFields as $field) {
                    if (!($field instanceOf SearchableField)) {
                        continue;
                    }

                    $fieldSearch = $field->getSearchStructure($model);
                    if (empty($fieldSearch)) {
                        continue;
                    }

                    foreach ($fieldSearch as $languageKey => $searchValue) {
                        if (!isset($search[$languageKey])) {
                            $search[$languageKey] = array();
                            $search[$languageKey]["content_type"] = $this->getType();
                            $search[$languageKey]["group_label"] = trans("backend.{$this->getType()}_plural");
                        }

                        if (!isset($search[$languageKey]["{$level}_search"])) {
                            $search[$languageKey]["{$level}_search"] = "";
                        }

                        $search[$languageKey]["{$level}_search"] = $search[$languageKey]["{$level}_search"]." ".$searchValue;
                    }
                }
            }
        }

        if (!empty($searchData["display"])) {
            foreach ($searchData["display"] as $displayType => $fieldName) {
                $field = $this->fields->find($fieldName);
                if (empty($field) || !($field instanceOf SearchableField)) {
                    continue;
                }

                $fieldSearch = $field->getSearchStructure($model, true);
                if (empty($fieldSearch)) {
                    continue;
                }

                foreach ($fieldSearch as $languageKey => $searchValue) {
                    if (!isset($search[$languageKey])) {
                        $search[$languageKey] = array();
                        $search[$languageKey]["content_type"] = $this->getType();
                        $search[$languageKey]["group_label"] = trans("backend.{$this->getType()}_plural");
                    }

                    $search[$languageKey][$displayType] = $searchValue;
                }

            }
        }


        if (empty($searchData["uri"])) {
            $websiteObject = $model->getActiveWebsiteEntry();

            if (!empty($websiteObject)) {
                foreach ($search as $languageKey => $searchValue) {
                    $woLang = $websiteObject->languages->findByLocale($languageKey);
                    if ($woLang && $woLang->lang_uri) {
                        $search[$languageKey]["uri"] = $woLang->lang_uri;
                    }
                }
            }
        } else {
            foreach ($search as $languageKey => $searchValue) {
                if (is_array($searchData["uri"])) {
                    $searchUri = $searchData["uri"][$languageKey];
                } else {
                    $searchUri = $searchData["uri"];
                }

                if (Str::contains($searchUri, "{type}") && isset($model->type)) {
                    if (isset($this->baseUri)) {
                        $baseUri = $this->baseUri[$model->type];
                        if (is_array($baseUri)) {
                            $searchUri = str_replace("{type}", $baseUri[$languageKey], $searchUri);
                        } else {
                            $searchUri = str_replace("{type}", $baseUri, $searchUri);
                        }
                    } else {
                        $searchUri = str_replace("{type}", $model->type, $searchUri);
                    }
                }

                if (Str::contains($searchUri, "{slug}")) {
                    $websiteObject = $model->getActiveWebsiteEntry();

                    if (!empty($websiteObject)) {
                        $woLang = $websiteObject->languages->findByLocale($languageKey);
                        $search[$languageKey]["uri"] = str_replace("{slug}", $woLang->lang_slug, $searchUri);
                    }
                } else {
                    $search[$languageKey]["uri"] = $searchUri;
                }
            }
        }
        return $search;
    }

    public function autoComplete($searchTerm)
    {
        $modelType = $this->modelType;
        $model = new $modelType();
        $query = $model->full()->where("title", 'like', "%".$searchTerm."%")
            ->select("id", "title", "id as object_id")
            ->orderBy("title", "asc")
            ->limit(10);
        $filters = $this->getFilters();

        foreach ($this->getFilters() as $filter) {
            if (is_null($filter["value"])) {
                $query->whereNull($filter["field"]);
            } else {
                $query->where($filter["field"], $filter["value"]);
            }
        }
        return $query->get();
    }

    public function toArray($onlyListable = false)
    {
        $array = array(
            'type' => $this->getType(),
            'label' => $this->getLabel(),
            'labelSingular' => $this->getSingularLabel(),
            'hierarchic' => $this->isHierarchic(),
            'order' => $this->isOrderable(),
            'templates' => $this->getTemplates(),
            'actions' => array(
                "grid" => $this->actions->getActionsByActionType(BaseAction::TYPE_GRID)->toArray(),
                "row" => $this->actions->getActionsByActionType(BaseAction::TYPE_ROW)->toArray()
            ),
            'fields' => array()
        );


        if ($onlyListable) {
            $fields = $this->fields->getListableFields();
        } else {
            $fields = $this->fields;
        }

        $array["fields"] = $fields->toArray();
        return $array;

    }

    public function toJson($options = 0)
    {
        return json_encode($this->toArray(), $options);
    }
}
