<?php

class fieldListBitmask extends cmsFormField {

    public $title       = LANG_PARSER_LIST_MULTIPLE;
    public $sql         = 'varchar({max_length}) NULL DEFAULT NULL';
    public $allow_index = true;
    public $filter_type = 'str';
    public $var_type    = 'array';

    public function getOptions() {
        return [
            new fieldCheckbox('is_checkbox_multiple', [
                'title'   => LANG_PARSER_BITMASK_CHECKBOX_MULTIPLE,
                'default' => true
            ]),
            new fieldString('list_class', [
                'title'   => LANG_PARSER_BITMASK_LIST_CLASS,
                'default' => 'multiple_tags_list',
                'extended_option' => true
            ]),
            new fieldNumber('max_length', [
                'title'   => LANG_PARSER_BITMASK_MAX,
                'hint'    => LANG_PARSER_BITMASK_MAX_HINT,
                'default' => 64,
                'rules'   => [
                    ['min', 1]
                ]
            ]),
            new fieldCheckbox('is_autolink', [
                'title'   => LANG_PARSER_LIST_IS_AUTOLINK,
                'hint'    => LANG_PARSER_LIST_IS_AUTOLINK_FILTER,
                'default' => false,
                'extended_option' => true
            ])
        ];
    }

    public function setOptions($options){

        parent::setOptions($options);

        if (empty($this->items)){
            $this->items = $this->getListItems();
        }

        if ($this->hasDefaultValue() && strpos($this->default, "\n") !== false){
            $this->default = null;
        }
    }

    public function getFilterInput($value) {

        if (!$this->show_filter_input_title) {
            $this->element_title = '';
        }

        return $this->getInput($value);
    }

    public function getSelectedValues($value) {

        if (is_empty_value($value)) {
            return [];
        }

        $list = [];

        if ($this->items) {

            $pos = 0;

            $is_array = is_array($value);

            foreach ($this->items as $key => $name) {

                if (!$is_array) {

                    if (substr($value, $pos, 1) === '1') {
                        $list[$key] = $name;
                    }

                    $pos++;
                    if ($pos + 1 > strlen($value)) {
                        break;
                    }
                } else {

                    if (in_array($key, $value)) {
                        $list[$key] = $name;
                    }
                }
            }
        }

        return $list;
    }

    public function getStringValue($value) {

        $list = $this->getSelectedValues($value);

        if (!$list) {
            return '';
        }

        return implode(', ', $list);
    }

    public function parse($value) {

        $list = $this->getSelectedValues($value);

        if (!$list) {
            return '';
        }

        $html = '';

        $is_autolink = $this->getOption('is_autolink');

        $html .= '<ul class="' . $this->getOption('list_class') . ' list-unstyled">';

        foreach ($list as $key => $name) {

            if ($is_autolink) {
                $html .= '<li class="list-inline-item"><a class="listbitmask_autolink ' . $this->item['ctype_name'] . '_listbitmask_autolink" href="' . href_to($this->item['ctype_name']) . '?' . $this->name . '%5B%5D=' . urlencode($key) . '">' . html($name, false) . '</a></li>';
            } else {
                $html .= '<li class="list-inline-item"><span>' . html($name, false) . '</span></li>';
            }
        }

        $html .= '</ul>';

        return $html;
    }

    public function parseValue($values, $return_as_array = false) {

        if (!$values || !is_array($values)) {
            return '';
        }

        $value = $return_as_array ? [] : '';

        if ($this->items) {
            foreach ($this->items as $key => $title) {
                if ($return_as_array) {
                    if (in_array($key, $values)) {
                        $value[] = $key;
                    }
                } else {
                    $value .= in_array($key, $values) ? '1' : '0';
                }
            }
        }

        return $value;
    }

    public function store($value, $is_submitted, $old_value = null) {

        $value = $this->parseValue($value, ($this->context === 'filter'));

        if (is_string($value) && mb_strpos($value, '1') === false) {
            return '';
        }

        return $value;
    }

    public function storeFilter($value) {
        return $this->store($value, false);
    }

    public function applyFilter($model, $values) {

        if (!is_array($values)) {
            return parent::applyFilter($model, $values);
        }

        $filter = $this->parseValue($values);
        if (!$filter) {
            return parent::applyFilter($model, $values);
        }

        $filter = str_replace('0', '_', $filter) . '%';

        return $model->filterLike($this->name, $filter);
    }

    public function getInput($value) {

        $this->items = array_keys_to_string_type($this->items);
        $this->data['selected'] = [];

        $this->data['items'] = $this->items;
        $this->data['selected'] = array_keys($this->getSelectedValues($value));

        return parent::getInput($value);
    }

    public function hookAfterUpdate($content_table_name, $field, $field_old, $model) {

        $is_prop = !isset($field_old['name']);

        // Свойства
        if ($is_prop) {

            $model->selectOnly('i.item_id')->
                select('i.value');

            $model->filterEqual('prop_id', $field['id']);

            $val_field_name = 'value';
            $unq_field_name = 'item_id';

        } else {
            // Поля
            $model->selectOnly('i.id')->
                select('i.'.$field_old['name']);

            $val_field_name = $field_old['name'];
            $unq_field_name = 'id';
        }

        $items = $model->limit(false)->
                get($content_table_name, function ($item, $model)use ($val_field_name) {
            return $item[$val_field_name];
        }, $unq_field_name);

        if (!$items || trim($field_old['values']) === trim($field['values'])) {
            return parent::hookAfterUpdate($content_table_name, $field, $field_old, $model);
        }

        $old_rows = string_explode_list($field_old['values']);
        ksort($old_rows, SORT_NATURAL);
        $new_rows = string_explode_list($field['values']);
        ksort($new_rows, SORT_NATURAL);

        foreach ($items as $id => $item_value) {

            if (!$item_value) {
                continue;
            }

            // Формируем старый массив значений
            $old_item_values = [];

            $pos = 0;

            foreach ($old_rows as $key => $value) {
                if (substr($item_value, $pos, 1) === '1') {
                    $old_item_values[] = $key;
                }
                $pos++;
            }

            // Формируем новую битовую маску
            $new_item_value = '';

            foreach ($new_rows as $nkey => $title) {
                $new_item_value .= in_array($nkey, $old_item_values) ? '1' : '0';
            }

            if(strpos($new_item_value, '1') === false){
                $new_item_value = null;
            }

            // записываем обратно в базу
            if ($is_prop) {
                $model->filterEqual('prop_id', $field['id']);
            }

            $model->filterEqual($unq_field_name, $id)->updateFiltered($content_table_name, [
                $val_field_name => $new_item_value
            ], true);
        }

        return parent::hookAfterUpdate($content_table_name, $field, $field_old, $model);
    }

}
