<?php namespace Eae\Backoffice\Generic;

use Config;
use Eae\Exception\InvalidConfigurationException;
use Eae\Exception\InvalidPermissionException;
use LaravelLocalization;
use Website;
use Eae\Support\Contracts\ListableFieldInterface;
use Eae\Support\Contracts\ExternalFieldInterface;
use Eae\Support\Contracts\SearchableFieldInterface;
use Illuminate\Support\Contracts\JsonableInterface;
use Illuminate\Support\Contracts\ArrayableInterface;
use Auth;
use Eae\Backoffice\Generic\Actions\BaseAction;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Eae\Backoffice\Generic\Fields\TextBoxField;
use Eae\Backoffice\Generic\Fields\SelectBoxField;
use Eae\Backoffice\Generic\Fields\CheckBoxField;
use ContentTypeModel;
use Session;
use Input;
use RequestContext;
use Lang;

class ContentType implements ArrayableInterface, JsonableInterface{
    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 $showUri = false;
    protected $hasStatus = true;
    protected $fields;
    protected $actions;
    protected $baseUri = false;
    protected $parent = false;
    protected $search = false;
    protected $showId = false;
    protected $filters;

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

        if(is_string($config)){
            $config = Config::get("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 = Auth::backend()->user();

        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 = Lang::get('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["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 = [];
        }

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

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

        foreach($config["fields"] as $fieldConfig){
            if(empty($fieldConfig["type"])){
                InvalidConfigurationException("There are fields without a type in the configuration");
            }
            $fieldType = ucfirst($fieldConfig["type"]);
            $class = "Eae\\Backoffice\\Generic\\Fields\\{$fieldType}Field";
            $this->fields->push(new $class($fieldConfig));
        }
    }

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

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

    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 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 = Lang::get('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 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){
        $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->getForeignKey();

        $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->getForeignKey();
            $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());

        $queryBuilder->addSelect($websiteEntryModel->getTable() . ".status");

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

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

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

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

            return array(
                    "total"             => $paginator->getTotal(),
                    "current"           => $paginator->getCurrentPage(),
                    "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->getForeignKey();

        $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->getForeignKey();
            $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");
        $queryBuilder->addSelect($websiteEntryModel->getTable() . ".status");

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

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

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

        $rows = $queryBuilder->get();
        // var_dump(\DB::getQueryLog()); die;
        $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)
                );
        }

    }

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

        foreach($oriItems as $item){
            //var_dump($item->getActiveWebsiteEntry()->parent_id . '  ' . $parent_id); die;
            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"){
        $fields = $this->fields->getFieldsByPlacement($placement);
        $form = "";
        foreach($fields as $field){
            if($field instanceOf ExternalFieldInterface){
                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, $this->userHasPermission(), $hidden);
        }
        return $form;
    }

    public function toExternalForm($model, $placement = "main"){
        $fields = $this->fields->getExternalFields($placement);
        $form = "";
        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, $this->userHasPermission(), $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){
        $form = "";

        $slug = new TextBoxField(array("name" => 'lang_slug', 'label' => 'slug',
            'multiLanguage' => true, 'woMultilang' => true));
        $slugInput = Input::old("slug");
        $hidden = false;
        if(!$model->exists && empty($slugInput)){
            $hidden = true;
        }

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

        $form .= $status->toForm($model, true, !$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
            ));
            $form .= $templateSelect->toForm($model, $this->userHasPermission());
        }
        if ($model->exists && ($this->baseUri || $this->hasTemplate())) {
            $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'] = Input::get("lang_slug");
        $values['status'] = Input::get("status");
        $values['template'] = Input::get("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 = array_where($errors->toArray(), function($key, $value) use($locale){
                return ends_with($key,"." . $locale) || str_contains($key, ".{$locale}.");
            });

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

    }
    /*
    public function getScripts(){
        $scripts = array(
            'genericForm' => Config::get('path.backoffice.js_path') . '/view/backend-generic-form.js',
            'langPicker' => Config::get('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 = Auth::backend()->user();
        if(empty($user)){
            return false;
        }

        return $user->hasPermission("cms.manage");
    }
    public function getSearch() {
        return $this->search;
    }

    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 SearchableFieldInterface)){
                          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"] = Lang::get("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 SearchableFieldInterface)){
                    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"] = Lang::get("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[$websiteId][$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);
    }
}
