<?php
/**
 * Класс модели, предназначенный для бэкенда
 */
class modelBackendWidgets extends modelWidgets {

    public function getLayoutRow($id) {
        return $this->getItemById('layout_rows', $id, function ($item, $model) {
            $item['options'] = cmsModel::stringToArray($item['options']);
            return $item;
        });
    }

    public function getLayoutCol($id) {
        return $this->getItemById('layout_cols', $id, function ($item, $model) {
            $item['options'] = cmsModel::stringToArray($item['options']);
            return $item;
        });
    }

    public function addLayoutRow($row, $default_col = []) {

        $row['ordering'] = $this->filterEqual('template', $row['template'])->
                getNextOrdering('layout_rows');

        $row_id = $this->insert('layout_rows', $row, true);

        if (!empty($row['cols_count'])) {
            for ($i = 0; $i < $row['cols_count']; ++$i) {
                $this->addLayoutCol([
                    'row_id'  => $row_id,
                    'title'   => $i + 1,
                    'options' => $default_col['options']
                ]);
            }
        }

        cmsCache::getInstance()->clean('layout.rows');

        return $row_id;
    }

    public function updateLayoutRow($id, $row) {

        cmsCache::getInstance()->clean('layout.rows');

        return $this->update('layout_rows', $id, $row, false, true);
    }

    public function deleteLayoutRow($id) {

        $this->filterEqual('row_id', $id);
        $this->deleteFiltered('layout_cols');

        cmsCache::getInstance()->clean('layout.rows');

        return $this->delete('layout_rows', $id);
    }

    public function deleteLayoutCol($id) {

        cmsCache::getInstance()->clean('layout.rows');

        return $this->delete('layout_cols', $id);
    }

    public function addLayoutCol($col) {

        $col['ordering'] = $this->filterEqual('row_id', $col['row_id'])->
                getNextOrdering('layout_cols');

        $id = $this->insert('layout_cols', $col, true);

        if (empty($col['name'])) {

            $this->update('layout_cols', $id, [
                'name' => 'pos_' . $id
            ]);
        } else {
            cmsCache::getInstance()->clean('layout.rows');
        }

        return $id;
    }

    public function updateLayoutCol($id, $col) {

        $this->update('layout_cols', $id, $col, false, true);

        cmsCache::getInstance()->clean('layout.rows');

        return $id;
    }

    public function addPage($page) {

        if (isset($page['url_mask']) && is_array($page['url_mask'])) {
            $page['url_mask'] = implode("\n", $page['url_mask']);
        }

        if (isset($page['url_mask_not']) && is_array($page['url_mask_not'])) {
            $page['url_mask_not'] = implode("\n", $page['url_mask_not']);
        }

        cmsCache::getInstance()->clean('widgets.pages');

        return $this->insert('widgets_pages', $page);
    }

    public function updatePage($id, $page) {

        cmsCache::getInstance()->clean('widgets.pages');

        return $this->update('widgets_pages', $id, $page);
    }

    public function deletePage($id) {

        // получаем привязанные виджеты
        $wb = $this->selectOnly('bind_id')->
                filterEqual('page_id', $id)->
                get('widgets_bind_pages', false, 'bind_id');

        // если есть, удаляем привязки и удаляем общие настройки
        if ($wb) {

            // удаляем привязки
            $this->filterEqual('page_id', $id);
            $this->deleteFiltered('widgets_bind_pages');

            // настройки виджетов
            $this->filterIn('id', array_keys($wb));
            $this->deleteFiltered('widgets_bind');

            cmsCache::getInstance()->clean('widgets.bind_pages');
        }

        cmsCache::getInstance()->clean('widgets.pages');

        return $this->delete('widgets_pages', $id);
    }

    public function getPage($id) {

        $this->useCache('widgets.pages');

        $this->joinLeft('content_types', 'ct', "i.name LIKE concat(ct.name, '.%')")->select('ct.title', 'title_subject_ctype');

        return $this->getItemById('widgets_pages', $id, function ($item, $model) {

            $item['groups']    = cmsModel::yamlToArray($item['groups']);
            $item['countries'] = cmsModel::yamlToArray($item['countries']);

            $item['is_custom'] = !empty($item['title']);

            if (!$item['title_subject']) {
                $item['title_subject'] = $item['title_subject_ctype'];
            }

            $item['title'] = !empty($item['title']) ?
                    $item['title'] :
                    sprintf(constant($item['title_const']), $item['title_subject']);

            return $item;
        });
    }

    public function getPagesByName($controller_name, $name) {

        $name = str_replace('*', '%', $name);

        $this->filterEqual('controller', $controller_name);
        $this->filterLike('name', $name);

        $this->useCache('widgets.pages');

        return $this->get('widgets_pages');
    }

    public function deletePagesByName($controller_name, $name) {

        $name = str_replace('*', '%', $name);

        $pages = $this->getPagesByName($controller_name, $name);

        if ($pages) {
            foreach ($pages as $page) {
                $this->deleteWidgetPageBind($page['id'], 'page_id');
            }
        }

        $this->filterLike('name', $name);

        cmsCache::getInstance()->clean('widgets.pages');

        return $this->deleteFiltered('widgets_pages');
    }

    public function deletePageWidgets($page_id) {
        return $this->deleteWidgetPageBind($page_id, 'page_id');
    }

    public function getWidgetsPages() {

        $this->joinLeft('controllers', 'c', 'c.name = i.controller')->
                select('c.title', 'controller_title');

        $this->joinLeft('content_types', 'ct', "i.name LIKE concat(ct.name, '.%')")->
                selectTranslatedField('ct.title', 'content_types', 'title_subject');

        $this->orderByList([
            ['by' => 'controller', 'to' => 'asc'],
            ['by' => 'name', 'to' => 'asc'],
            ['by' => 'title', 'to' => 'asc'],
        ]);

        $items = $this->limit(false)->get('widgets_pages', function ($item, $model) {

            if (!$item['id']) {
                return false;
            }
            if (!$item['controller']) {
                $item['controller'] = 'custom';
            }

            $item['title'] = !empty($item['title']) ?
                    $item['title'] :
                    sprintf(constant($item['title_const']), $item['title_subject']);

            return $item;
        }) ?: [];

        $result = [
            'core' => [
                'name' => 'core',
                'title' => LANG_WP_SYSTEM,
                'pages' => [
                    [
                        'title'  => LANG_WP_ALL_PAGES,
                        'key'    => 'core.0'
                    ],
                    [
                        'title'  => LANG_WP_HOME_PAGE,
                        'key'    => 'core.1'
                    ]
                ]
            ],
            'custom' => [
                'name' => 'custom',
                'title' => LANG_WP_CUSTOM,
                'pages' => []
            ]
        ];

        $last_controller = false;

        foreach ($items as $item) {
            if ($last_controller !== $item['controller']) {
                $result[$item['controller']] = $result[$item['controller']] ?? [
                    'name' => $item['controller'],
                    'title' => string_lang($item['controller'] . '_CONTROLLER', $item['controller_title'] ?? $item['controller']),
                    'pages' => []
                ];
            }

            $result[$item['controller']]['pages'][] = [
                'title'  => $item['title'],
                'key'    => "{$item['controller']}.{$item['id']}"
            ];

            $last_controller = $item['controller'];
        }

        return $result;
    }

    public function getAvailableWidgets() {

        $this->joinLeft('controllers', 'c', 'c.name = i.controller')->
                select('c.title', 'controller_title');

        $widgets = $this->orderByList([
                ['by' => 'controller', 'to' => 'asc'],
                ['by' => 'name', 'to' => 'asc']
            ])->get('widgets', function ($item, $model) {
                if ($item['image_hint_path']) {
                    $item['image_hint_path'] = cmsConfig::get('upload_host') . '/' . $item['image_hint_path'];
                }
                $item['controller_title'] = $item['controller'] ?
                        string_lang($item['controller'] . '_CONTROLLER', $item['controller_title']) :
                        LANG_CP_WIDGETS_MISC;
                return $item;
        }) ?: [];

        $sorted = [];

        foreach ($widgets as $widget) {

            $key = $widget['controller'] ? $widget['controller'] : '0';

            $sorted[$key][] = $widget;
        }

        return $sorted;
    }

    public function getWidget($id) {
        return $this->getItemById('widgets', $id);
    }

    public function getWidgetBinding($id) {

        $this->select('w.controller', 'controller');
        $this->select('w.name', 'name');
        $this->select('w.title', 'widget_title');
        $this->select('w.image_hint_path', 'image_hint_path');

        $this->join('widgets', 'w', 'w.id = i.widget_id');

        $this->useCache('widgets.bind');

        return $this->getItemById('widgets_bind', $id, function ($item, $model) {
            if ($item['image_hint_path']) {
                $item['image_hint_path'] = cmsConfig::get('upload_host') . '/' . $item['image_hint_path'];
            }
            $item['options']          = cmsModel::yamlToArray($item['options']);
            $item['groups_view']      = cmsModel::yamlToArray($item['groups_view']);
            $item['groups_hide']      = cmsModel::yamlToArray($item['groups_hide']);
            $item['device_types']     = cmsModel::yamlToArray($item['device_types']);
            $item['template_layouts'] = cmsModel::yamlToArray($item['template_layouts']);
            $item['languages']        = cmsModel::yamlToArray($item['languages']);
            $item['is_set_access']    = !empty($item['groups_view']) || $item['groups_hide'];
            return $item;
        });
    }

    public function getWidgetBindingsScheme($page_id, $page_ids, $template_name) {

        $binds = $this->
                filterStart()->
                filterEqual('bp.template', $template_name)->
                filterOr()->
                filterIsNull('bp.template')->
                filterEnd()->
                select('w.title', 'name')->
                select('w.image_hint_path', 'image_hint_path')->
                select('bp.*')->
                select('wp.title_const', 'page_title_const')->
                select('wp.title', 'page_title')->
                select('ct.title', 'page_title_subject')->
                select('IFNULL(bp.bind_id,i.id)', 'bind_id')->
                joinInner('widgets', 'w', 'w.id = i.widget_id')->
                joinLeft('widgets_bind_pages', 'bp', 'bp.bind_id = i.id')->
                joinLeft('widgets_pages', 'wp', 'wp.id = bp.page_id')->
                joinLeft('content_types', 'ct', "wp.name LIKE concat(ct.name, '.%')")->
                orderBy('bp.position, bp.ordering')->
                get('widgets_bind') ?: [];

        $positions = [];

        foreach ($binds as $bind) {

            $bind['languages']    = cmsModel::yamlToArray($bind['languages']);
            $bind['device_types'] = cmsModel::yamlToArray($bind['device_types']);
            $bind['groups_view']  = cmsModel::yamlToArray($bind['groups_view']);

            if ($bind['device_types'] && count($bind['device_types']) < 3) {

                $device_types = [];

                foreach ($bind['device_types'] as $dt) {
                    $device_types[] = string_lang('LANG_' . $dt . '_DEVICES');
                }
            } else {
                $device_types = false;
            }

            if (!$bind['position']) {
                $bind['position'] = '_unused';
            }

            if ($bind['image_hint_path']) {
                $bind['image_hint_path'] = cmsConfig::get('upload_host') . '/' . $bind['image_hint_path'];
            }

            if ($bind['page_id'] == 1) {
                $bind['page_title'] = LANG_WP_HOME_PAGE;
            }

            $positions[$bind['position']][] = [
                'id'                => $bind['id'],
                'bind_id'           => $bind['bind_id'],
                'widget_id'         => $bind['widget_id'],
                'title'             => string_replace_svg_icons($bind['title']),
                'page_title'        => $bind['page_title'] ?:
                        ($bind['page_title_const'] ? sprintf(constant($bind['page_title_const']), $bind['page_title_subject']) : ''),
                'position'          => $bind['position'],
                'languages'         => $bind['languages'],
                'image_hint_path'   => $bind['image_hint_path'],
                'device_type_names' => $bind['device_types'],
                'device_types'      => $device_types,
                'name'              => $bind['name'],
                'is_set_access'     => !empty($bind['groups_view']) || $bind['groups_hide'],
                'is_tab_prev'       => boolval($bind['is_tab_prev']),
                'is_enabled'        => boolval($bind['is_enabled']),
                'is_hidden'         => (!in_array($bind['page_id'], $page_ids) && $bind['position'] !== '_unused'),
                'is_disabled'       => ($bind['page_id'] != $page_id && $bind['position'] !== '_unused')
            ];
        }

        return $positions ? $positions : false;
    }

    public function addWidgetBinding($widget, $page_id, $position, $template) {

        cmsCache::getInstance()->clean('widgets.bind');

        $bind_id = $this->insert('widgets_bind', [
            'widget_id' => $widget['id'],
            'title'     => $widget['title']
        ]);

        if (!$bind_id) {
            return false;
        }

        $bp_id = $this->addWidgetBindPage($bind_id, $page_id, $position, $template);

        return ['id' => $bind_id, 'bp_id' => $bp_id];
    }

    public function updateWidgetBinding($id, $widget) {

        if ($widget['template_layouts'] === ['0']) {
            $widget['template_layouts'] = null;
        }
        if ($widget['languages'] === ['0']) {
            $widget['languages'] = null;
        }
        if ($widget['groups_view'] === ['0']) {
            $widget['groups_view'] = null;
        }
        if ($widget['device_types'] === ['0']) {
            $widget['device_types'] = null;
        }

        cmsCache::getInstance()->clean('widgets.bind');

        return $this->update('widgets_bind', $id, $widget);
    }

    public function deleteWidgetBinding($id) {

        $this->deleteWidgetPageBind($id, 'bind_id');

        cmsCache::getInstance()->clean('widgets.bind');

        return $this->delete('widgets_bind', $id);
    }

    public function getWidgetBindPage($id) {
        return $this->getItemById('widgets_bind_pages', $id);
    }

    public function copyWidgetByPage($bp_id) {

        $binding_page = $this->getWidgetBindPage($bp_id);
        if (!$binding_page) {
            return false;
        }

        $widget_bind = $this->getItemById('widgets_bind', $binding_page['bind_id']);
        if (!$widget_bind) {
            return false;
        }

        cmsCache::getInstance()->clean('widgets.bind');

        $ordering = $this->filterEqual('page_id', $binding_page['page_id'])->
                filterEqual('position', $binding_page['position'])->
                getNextOrdering('widgets_bind_pages');

        $widget_bind['title'] .= ' (' . $ordering . ')';
        unset($widget_bind['id']);

        $bind_id = $this->insert('widgets_bind', $widget_bind);
        if (!$bind_id) {
            return false;
        }

        $new_bp_id = $this->addWidgetBindPage(
            $bind_id,
            $binding_page['page_id'],
            $binding_page['position'],
            $binding_page['template'],
            $ordering,
            $binding_page['is_enabled']
        );

        return ['id' => $bind_id, 'bp_id' => $new_bp_id];
    }

    public function getWidgetBindPageCount($bind_id) {
        return $this->filterEqual('bind_id', $bind_id)->getCount('widgets_bind_pages', 'id', true);
    }

    public function addWidgetBindPage($bind_id, $page_id, $position, $template, $ordering = null, $is_enabled = 1) {

        cmsCache::getInstance()->clean('widgets.bind_pages');
        cmsCache::getInstance()->clean('widgets.bind');
        cmsCache::getInstance()->clean('widgets.pages');

        return $this->insert('widgets_bind_pages', [
            'template'   => $template,
            'page_id'    => $page_id,
            'bind_id'    => $bind_id,
            'position'   => $position,
            'is_enabled' => $is_enabled,
            'ordering'   => is_null($ordering) ? $this->
                    filterEqual('page_id', $page_id)->
                    filterEqual('position', $position)->
                    getNextOrdering('widgets_bind_pages') : $ordering
        ]);
    }

    public function updateWidgetBindPosition($old_pos, $new_pos, $template) {
        cmsCache::getInstance()->clean('widgets.bind');
        cmsCache::getInstance()->clean('widgets.bind_pages');
        cmsCache::getInstance()->clean('widgets.pages');
        $this->filterEqual('template', $template);
        $this->filterEqual('position', $old_pos);
        return $this->updateFiltered('widgets_bind_pages', ['position' => $new_pos], true);
    }

    public function updateWidgetBindPage($id, $item) {
        cmsCache::getInstance()->clean('widgets.bind_pages');
        cmsCache::getInstance()->clean('widgets.bind');
        cmsCache::getInstance()->clean('widgets.pages');
        return $this->update('widgets_bind_pages', $id, $item);
    }

    public function deleteWidgetPageBind($id, $by = 'id') {
        cmsCache::getInstance()->clean('widgets.bind_pages');
        cmsCache::getInstance()->clean('widgets.bind');
        cmsCache::getInstance()->clean('widgets.pages');
        return $this->filterEqual($by, $id)->deleteFiltered('widgets_bind_pages');
    }

    public function deleteWidget($id) {

        $wb = $this->filterEqual('widget_id', $id)->get('widgets_bind');

        if ($wb) {

            $this->filterIn('bind_id', array_keys($wb));
            $this->deleteFiltered('widgets_bind_pages');

            cmsCache::getInstance()->clean('widgets.bind_pages');
        }

        $this->filterEqual('widget_id', $id);
        $this->deleteFiltered('widgets_bind');

        cmsCache::getInstance()->clean('widgets.pages');
        cmsCache::getInstance()->clean('widgets.bind');

        return $this->delete('widgets', $id);
    }

    public function reorderWidgetsBindings($position, $items, $template, $page_id = 0) {

        if ($position === '_unused') {
            $page_id = null;
        }

        $in = [];
        foreach ($items as $item) {
            if (!empty($item['bp_id'])) {
                $in[] = intval($item['bp_id']);
            }
        }

        $now = $in ? $this->filterIn('id', $in)->get('widgets_bind_pages') : [];

        $new = [];

        foreach ($items as $ordering => $item) {

            if (!empty($item['bp_id']) && !empty($now[$item['bp_id']])) {

                $update_data = [
                    'ordering' => $ordering,
                    'position' => $position,
                    'template' => $template
                ];

                if(empty($item['is_disabled'])){
                    $update_data['page_id'] = $page_id;
                }

                $this->updateWidgetBindPage($item['bp_id'], $update_data);

            } else {
                // копия
                if ($this->filterEqual('id', $item['id'])->getCount('widgets_bind', 'id', true)) {

                    $id = $this->addWidgetBindPage($item['id'], $page_id, $position, $template, $ordering, ($position === '_unused') ? 0 : 1);

                    $new[$id] = $item['id']; // $item['id'] может быть одинаковый
                }
            }
        }

        return $new;
    }

    public function unbindAllWidgets($template_name) {
        $this->deleteWidgetPageBind($template_name, 'template');
    }

}
