<?php
/**
 * 2007-2022 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 * @author    PrestaShop SA <contact@prestashop.com>
 * @copyright 2007-2022 PrestaShop SA
 * @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */

require_once dirname(__FILE__) . '/AdminEtsHDFormController.php';
require_once dirname(__FILE__) . '/AdminEtsHDOptionsController.php';

class AdminEtsHDSettingsController extends AdminEtsHDFormController
{
    public $column_types;
    public $fields_form_option;
    public $field_type;

    public function __construct()
    {
        $this->bootstrap = true;

        $this->table = 'ets_hd_column';
        $this->className = 'HDColumn';
        $this->list_id = $this->table;
        $this->lang = true;
        $this->show_form_cancel_button = false;
        $this->list_no_link = true;

        parent::__construct();

        $this->column_types = array(
            'text' => array(
                'id' => 'text',
                'name' => $this->l('Text'),
            ),
            'numeric' => array(
                'id' => 'numeric',
                'name' => $this->l('Numeric'),
            ),
            'email' => array(
                'id' => 'email',
                'name' => $this->l('Email'),
            ),
            'textarea' => array(
                'id' => 'textarea',
                'name' => $this->l('Textarea'),
            ),
            'select' => array(
                'id' => 'select',
                'option' => true,
                'name' => $this->l('Select'),
            ),
            'radio' => array(
                'id' => 'radio',
                'option' => true,
                'name' => $this->l('Radio'),
            ),
            'checkbox' => array(
                'id' => 'checkbox',
                'option' => true,
                'name' => $this->l('Checkbox'),
            ),
            'file' => array(
                'id' => 'file',
                'name' => $this->l('File'),
            ),
            'date' => array(
                'id' => 'date',
                'name' => $this->l('Date'),
            ),
            'datetime' => array(
                'id' => 'datetime',
                'name' => $this->l('Datetime'),
            )
        );

        $this->field_type = HDDefines::getInstance()->getConfigsFieldType();

        $this->fields_options = array(
            'title' => $this->l('Settings'),
            'fields' => HDDefines::getInstance()->getConfigs(),
            'icon' => '',
            'submit' => array(
                'title' => $this->l('Save'),
            ),
        );

        $this->fields_form = array(
            'legend' => array(
                'title' => Tools::isSubmit('id_ets_hd_column') ? $this->l('Edit field') : $this->l('Add field'),
            ),
            'submit' => array(
                'title' => $this->l('Save'),
            ),
            'input' => array(
                'title' => array(
                    'name' => 'title',
                    'label' => $this->l('Title'),
                    'type' => 'text',
                    'lang' => true,
                    'required' => true,
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'title',
                    'size' => 255,
                    'desc' => $this->l('lorem: day la text hien thi ngoai front end/ back end. Vi du firt name'),
                ),
                'name' => array(
                    'name' => 'name',
                    'label' => $this->l('Name'),
                    'type' => 'text',
                    'required' => true,
                    'regex' => array(
                        array(
                            'pattern' => '/^[a-z][a-z0-9_]+$/',
                            'bool' => true,
                            'error' => $this->l('Column name is invalid'),
                        )
                    ),
                    'form_group_class' => 'name',
                    'size' => 255,
                    'desc' => $this->l('Lorem: day la ten de xy ly du lieu tren he thong, khong chap nhan dau cach, ky tu dac biet, chi chap nhan dau gach duoi. Vi du first_name'),
                ),
                'type' => array(
                    'name' => 'type',
                    'label' => $this->l('Type'),
                    'type' => 'select',
                    'options' => array(
                        'query' => $this->column_types,
                        'id' => 'id',
                        'name' => 'name',
                    ),
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'type',
                ),
                'field_type' => array(
                    'name' => 'field_type',
                    'label' => $this->l('Field type'),
                    'type' => 'select',
                    'options' => array(
                        'query' => $this->field_type,
                        'id' => 'id',
                        'name' => 'name',
                    ),
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'field_type',
                ),
                'field_length' => array(
                    'name' => 'field_length',
                    'label' => $this->l('Field length'),
                    'type' => 'text',
                    'col' => '9',
                    'regex' => array(
                        array(
                            'pattern' => '/^[1-9]([0-9]+)?(,[1-9]([0-9]+)?)?$/',
                            'bool' => true,
                            'error' => $this->l('Length is invalid. Input with syntax (integer) or (integer,integer). Example: 10 or 10,3'),
                        )
                    ),
                    'form_group_class' => 'field_length',
                ),
                'description' => array(
                    'name' => 'description',
                    'label' => $this->l('Description'),
                    'rows' => 5,
                    'type' => 'textarea',
                    'lang' => true,
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'description',
                    'size' => 255,
                ),
                'placeholder' => array(
                    'name' => 'placeholder',
                    'label' => $this->l('Placeholder'),
                    'type' => 'text',
                    'lang' => true,
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'placeholder',
                    'size' => 255,
                ),
                'default' => array(
                    'name' => 'default',
                    'label' => $this->l('Default value'),
                    'rows' => 5,
                    'type' => 'textarea',
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'default textarea',
                ),
                'default_date' => array(
                    'name' => 'default',
                    'id'=>'default_date',
                    'label' => $this->l('Default value'),
                    'rows' => 5,
                    'type' => 'date',
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'default date',
                ),
                'default_datetime' => array(
                    'name' => 'default',
                    'id'=>'default_datetime',
                    'label' => $this->l('Default value'),
                    'rows' => 5,
                    'type' => 'datetime',
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'default datetime',
                ),
                'default_text' => array(
                    'name' => 'default',
                    'label' => $this->l('Default value'),
                    'type' => 'text',
                    'validate' => 'isCleanHtml',
                    'form_group_class' => 'default text',
                ),
                'display_field' => array(
                    'name' => 'display_field',
                    'label' => $this->l('Display field in list front office'),
                    'type' => 'switch',
                    'values' => array(
                        array(
                            'id' => 'display_field_on',
                            'value' => 1,
                            'label' => $this->l('Yes'),
                        ),
                        array(
                            'id' => 'display_field_off',
                            'value' => 0,
                            'label' => $this->l('No'),
                        ),
                    ),
                    'validate' => 'isBool',
                    'form_group_class' => 'display_field',
                ),
                'display_field_admin' => array(
                    'name' => 'display_field_admin',
                    'label' => $this->l('Display field in list back office'),
                    'type' => 'switch',
                    'values' => array(
                        array(
                            'id' => 'display_field_admin_on',
                            'value' => 1,
                            'label' => $this->l('Yes'),
                        ),
                        array(
                            'id' => 'display_field_admin_off',
                            'value' => 0,
                            'label' => $this->l('No'),
                        ),
                    ),
                    'validate' => 'isBool',
                    'form_group_class' => 'display_field',
                ),
                'required' => array(
                    'name' => 'required',
                    'label' => $this->l('Is required'),
                    'type' => 'switch',
                    'values' => array(
                        array(
                            'id' => 'required_on',
                            'value' => 1,
                            'label' => $this->l('Yes'),
                        ),
                        array(
                            'id' => 'required_off',
                            'value' => 0,
                            'label' => $this->l('No'),
                        ),
                    ),
                    'validate' => 'isBool',
                    'form_group_class' => 'required',
                ),
                'active' => array(
                    'name' => 'active',
                    'label' => $this->l('Enabled'),
                    'type' => 'switch',
                    'values' => array(
                        array(
                            'id' => 'active_on',
                            'value' => 1,
                            'label' => $this->l('Yes'),
                        ),
                        array(
                            'id' => 'active_off',
                            'value' => 0,
                            'label' => $this->l('No'),
                        ),
                    ),
                    'default_value' => 1,
                    'validate' => 'isBool',
                    'form_group_class' => 'active',
                )
            ),
            'buttons' => array(
                'back' => array(
                    'href' => self::$currentIndex . '&token=' . $this->token,
                    'title' => $this->l('Cancel'),
                    'icon' => 'process-icon-cancel',
                    'class' => 'ets_hd_cancel'
                ),
            )
        );

        $this->fields_form_option = array(
            'id_ets_hd_option' => array(
                'name' => 'id_ets_hd_option',
                'label' => $this->l('Id option'),
                'type' => 'hidden'
            ),
            'title' => array(
                'name' => 'title',
                'label' => $this->l('Option label'),
                'type' => 'text',
                'lang' => true,
                'required' => true,
                'validate' => 'isCleanHtml',
                'size' => 255,
                'class' => 'ets_hd_title_character',
            ),
            'default' => array(
                'name' => 'default',
                'label' => $this->l('Default'),
                'type' => 'hidden',
                'validate' => 'isBool',
            ),
            'deleted' => array(
                'name' => 'deleted',
                'label' => $this->l('Deleted'),
                'type' => 'hidden',
                'default' => 0,
            ),
        );
    }

    public function setMedia($isNewTheme = false)
    {
        parent::setMedia($isNewTheme);
        $this->addJqueryUI('ui.widget');
        $this->addjQueryPlugin('tagify', null, false);
        $this->addJqueryUI('ui.sortable');
        $this->addJqueryUI('ui.draggable');
    }

    public function initContent()
    {
        parent::initContent();

        $this->content .= $this->renderListColumns();

        $this->context->smarty->assign([
            'content' => $this->content,
        ]);
    }

    public function renderListColumns()
    {
        $this->context->smarty->assign(array(
            'content' => $this->loadObject(true) ? $this->renderForm() :'',
        ));

        return $this->context->smarty->fetch($this->module->getLocalPath() . 'views/templates/admin/helpers/form/list-column.tpl');
    }

    public function renderItemColumn()
    {
        if ($this->object->id <= 0) {
            return '';
        }
        $this->context->smarty->assign(array(
            'column' => HDColumn::getColumns($this->object->id, false, 0, 0, 0, null, $this->context),
            'base_link' => $this->context->link->getAdminLink('AdminEtsHDSettings'),
        ));

        return $this->context->smarty->fetch($this->module->getLocalPath() . 'views/templates/admin/helpers/form/list-column-item.tpl');
    }

    public function renderOptions($ret = false)
    {
        $this->tpl_option_vars['sub_tabs'] = array(
            'info' => $this->l('Info'),
            'field' => $this->l('Field list'),
            'general' => $this->l('General'),
            'condition' => $this->l('Condition'),
            'staff' => $this->l('Staff info'),
            'email' => $this->l('Email'),
        );
        $current_tab = Tools::getValue('current_tab');
        if (trim($current_tab) == '' ||
            !Validate::isCleanHtml($current_tab)
        ) {
            $current_tab = 'info';
        }
        $this->tpl_option_vars['current_tab'] = $current_tab;
        $this->tpl_option_vars['columns'] = HDColumn::getColumns(0, false, 0, 0, 0, null, $this->context);
        $this->tpl_option_vars['base_link'] = $this->context->link->getAdminLink('AdminEtsHDSettings');
        $this->tpl_option_vars['PS_ATTACHMENT_MAXIMUM_SIZE'] = HDTools::formatBytes(HDTools::getPostMaxSizeBytes());
        $this->tpl_option_vars['base_dir'] = _PS_MODULE_DIR_ . 'ets_helpdesk/cronjob.php';
        $this->tpl_option_vars['php_path'] = (defined('PHP_BINDIR') && PHP_BINDIR && is_string(PHP_BINDIR) ? PHP_BINDIR.'/' : '').'php ';
        if($cronjob_time = Configuration::getGlobalValue('ETS_HD_CRONJOB_TIME'))
        {
            $cronjob_last ='';
            $last_time = strtotime($cronjob_time);
            $time = strtotime(date('Y-m-d H:i:s'))-$last_time;
            if($time > 86400)
                $cronjob_last = Tools::displayDate($cronjob_time,null,true);
            elseif($time)
            {
                if($hours =floor($time/3600))
                {
                    $cronjob_last .= $hours.' '.$this->l('hours').' ';
                    $time = $time%3600;
                }
                if($minutes = floor($time/60))
                {
                    $cronjob_last .= $minutes.' '.$this->l('minutes').' ';
                    $time = $time%60;
                }
                if($time)
                    $cronjob_last .= $time.' '.$this->l('seconds').' ';
                $cronjob_last .= $this->l('ago');
            }  
            $this->tpl_option_vars['cronjob_last']   = $cronjob_last;
        }
        return parent::renderOptions($ret);
    }

    public function getTemplateFormVars()
    {
        $values = HDOption::getOptions($this->object->id);
        $this->tpl_form_vars['form_option'] = array(
            'fields' => $this->fields_form_option,
            'values' => $values,
        );
        if (!$values) {
            $defaults = array();
            for ($ik = 0; $ik < 2; $ik++) {
                $defaults[] = Tools::strtolower(Tools::passwdGen(8));
            }
            $this->tpl_form_vars['form_option']['defaults'] = $defaults;
        }
        return $this->tpl_form_vars;
    }

    public function ajaxProcessRenderForm()
    {
        if (!$this->loadObject(true)) {
            return;
        }
        $this->ajaxJson(array(
            'form' => $this->renderForm(),
        ));
    }

    /**
     * @var HDColumn
     */
    public $keep_old_object;

    /**
     * @param HDColumn $object
     * @param string $table
     */
    public function copyFromPost(&$object, $table)
    {
        $this->keep_old_object = clone $object;

        parent::copyFromPost($object, $table);

        if (trim($object->type) !== ''
            && isset($this->column_types[$object->type])
            && $this->column_types[$object->type]
        ) {
            switch ($object->type) {
                case 'date':
                    $object->field_type = 'date';
                    break;
                case 'datetime':
                    $object->field_type = 'datetime';
                    break;
                case 'file':
                case 'select':
                case 'radio':
                case 'checkbox':
                    $object->field_type = 'varchar';
                    $object->field_length = 255;
                    break;
            }
        }
        if (property_exists($object, 'position')
            && method_exists($object, 'lastPosition')
        ) {
            if ($this->keep_old_object->id <= 0)
                $object->position = (int)$object->lastPosition() + 1;
        }
    }

    public function addTicketColumn()
    {
        if (count($this->errors) > 0 ||
            $this->object->id <= 0 ||
            !$this->object instanceof HDColumn
        ) {
            $this->errors[] = $this->l('Object does not exist.');
        } elseif ($this->object->type !== '' && isset($this->column_types[$this->object->type])) {
            $field_length = $this->object->field_length > 0 ? $this->object->field_length : (isset($this->field_type[$this->object->field_type]) && isset($this->field_type[$this->object->field_type]['default']) ? $this->field_type[$this->object->field_type]['default'] : '');
            $struct_field = $this->object->field_type . (trim($field_length) !== '' ? ' (' . $field_length . ')' : '') . ' DEFAULT NULL';

            if (trim($struct_field) == '') {
                $this->errors[] = $this->l('Struct field is empty.');
            } else {
                $schema_fields = HDTicket::getSchema();
                if ($this->keep_old_object->id > 0) {
                    if (trim($this->object->name) !== $this->keep_old_object->name) {
                        if (in_array($this->object->name, $schema_fields)) {
                            $this->errors[] = $this->l('Column is exist in table.');
                        } elseif (in_array($this->keep_old_object->name, $schema_fields)) {
                            if (!HDTicket::changeColumn($this->keep_old_object->name, $this->object->name, $struct_field))
                                $this->errors[] = $this->l('Cannot change column in table');
                        }
                    } elseif (trim($this->object->field_type) !== trim($this->keep_old_object->field_type) || trim($this->object->field_length) !== trim($this->keep_old_object->field_length)) {
                        if (!HDTicket::modifyColumn($this->object->name, $struct_field))
                            $this->errors[] = $this->l('Cannot modify column in table');
                    }
                } elseif ($this->keep_old_object->id <= 0 && !in_array($this->object->name, $schema_fields)) {
                    if (!HDTicket::addColumn($this->object->name, $struct_field))
                        $this->errors[] = $this->l('Cannot add column in table');
                }
            }
        } else
            $this->errors[] = $this->l('Type column is not exist.');
        if (count($this->errors)) {
            $this->ajaxJson(array(
                'errors' => implode(PHP_EOL, $this->errors),
            ));
        }
    }

    public function addColumnOptions()
    {
        $cache_options = array();
        if (!count($this->errors)
            && $this->object instanceof HDColumn
            && $this->object->id > 0
            && HDColumn::hasOptions($this->object->type)
            && !count($this->op_errors)
        ) {
            $options = Tools::getValue('option');
            if (is_array($options)
                && count($options) > 0
            ) {
                $removeOpts = array();
                $addOpts = array();
                $languages = Language::getLanguages(false);
                $id_lang_default = (int)Configuration::get('PS_LANG_DEFAULT');
                $indexes = array();
                $ik = 1;

                foreach ($options as $key => $op) {
                    $id_ets_hd_option = isset($op['id_ets_hd_option']) && $op['id_ets_hd_option'] > 0 && Validate::isUnsignedId($op['id_ets_hd_option']) ? (int)$op['id_ets_hd_option'] : null;
                    $option = new HDOption($id_ets_hd_option);
                    if (isset($op['deleted']) && (int)$op['deleted'] > 0) {
                        if ($option->delete()) {
                            $removeOpts[] = (int)$option->id;
                        }
                    } else {
                        $option->default = isset($op['default']) && $op['default'] ? 1 : 0;
                        if (is_array($languages) &&
                            count($languages) > 0
                        ) {
                            foreach ($languages as $l) {
                                $option->title[(int)$l['id_lang']] = isset($op['title_' . (int)$l['id_lang']]) && trim($op['title_' . (int)$l['id_lang']]) !== '' ? trim($op['title_' . (int)$l['id_lang']]) : $op['title_' . $id_lang_default];
                            }
                        }
                        $keep_old_id = $option->id;
                        if ($option->save()) {
                            $cache_options[$key] = $option;
                        }
                        if (!$keep_old_id)
                            $addOpts[] = (int)$option->id;

                        $indexes[$option->id] = $ik++;
                    }
                }
                if ($this->object instanceof HDColumn &&
                    $this->object->id > 0
                ) {
                    if (count($removeOpts) > 0) {
                        $this->object->removeOptions($removeOpts);
                    }
                    if (count($addOpts) > 0) {
                        $this->object->addOptions($addOpts);
                    }
                    if (count($indexes) > 0) {
                        $this->object->updatePositionOptions($indexes);
                    }
                }
            }
        }

        return $cache_options;
    }

    public $op_errors = array();

    public function validateRules($class_name = null)
    {
        parent::validateRules($class_name);

        if (!count($this->errors)) {
            if ((int)Tools::getValue($this->identifier) <= 0 && trim(($name = Tools::getValue('name'))) !== '' && in_array($name, HDTicket::getSchema())) {
                $this->errors[] = $this->l('Column is exist in table.');
            }
        }
        // Validate options:
        $options = Tools::getValue('option');
        $type = trim(Tools::getValue('type'));
        $field_length = trim(Tools::getValue('field_length'));
        $field_type = trim(Tools::getValue('field_type'));
        $config_fields = HDDefines::getInstance()->getConfigsFieldType($field_type);
        if ($field_length == '' && $config_fields && isset($config_fields['default']) && $config_fields['default'] !== '') {
            $field_length = $config_fields['default'];
        }
        $size = $field_length;
        if($field_length!=='' && ($field_length <=0 || !Validate::isUnsignedInt($field_length)))
            $this->errors[] = $this->l('Field lang is not valid');
        if (HDColumn::hasOptions($type)
        ) {
            if(is_array($options)
            && count($options) > 0)
            {
                foreach ($options as $key => $op) {
                    if (!isset($op['deleted']) ||
                        (int)$op['deleted'] <= 0
                    ) {
                        $res = $this->validateOptionFields($op);
                        if ($res !== true) {
                            $this->op_errors[$key] = $res;
                        }
                    }
                    if(isset($this->op_errors[$key]) && $this->op_errors[$key])
                        $this->errors[]= $this->l('All options is required');
                }
            }
            else
                $this->errors[]= $this->l('Options is required');
        }
        //Custom:
        $default = Tools::getValue('default');
        if ($type == 'file' || HDColumn::hasOptions($type)) {
            if ((int)$size < 255) {
                $size = 255;
            }
            if (Tools::strlen($default) > (int)$size) {
                $this->errors[] = sprintf($this->l('Default value error. Maximum %d characters'), $size);
            }
        } else {
            if (trim($field_length) !== '' && $field_type !== 'decimal') {
                switch ($field_type) {
                    case 'varchar':
                        if ($field_length > 65535) { // 65535
                            $this->errors[] = $this->l('Field length is invalid. Please input number less than maximum 65535');
                        }
                        break;
                    case 'char':
                        if ($field_length > 255) {
                            $this->errors[] = $this->l('Field length is invalid. Please input number less than maximum 255');
                        }
                        break;
                    default:
                        if (!Validate::isUnsignedInt($field_length) || $field_length > 2147483647) {
                            $this->errors[] = $this->l('Field length is invalid. Please input number less than maximum 2147483647');
                        }
                        break;
                }
            } elseif (trim($field_length) !== '' && (!preg_match('/^\d{1,2}(\,\d{1,2})?$/', $field_length) || ($field_length_split = explode(',', $field_length)) && (int)$field_length_split[0] <= (int)$field_length_split[1])) {
                $this->errors[] = $this->l('Field length is invalid. Please input with struct "aa.bb" and aa > bb');
            }
            if (trim($default) !== '') {
                // Validate default:
                switch ($field_type) {
                    case 'int':
                        if (!Validate::isUnsignedInt($default) || (int)$default > 2147483647) {
                            $this->errors[] = $this->l('Default value is invalid. Please input number less than maximum 4294967295');
                        }
                        break;
                    case 'tinyint':
                        if (!Validate::isUnsignedInt($default) || (int)$default > 127) {
                            $this->errors[] = $this->l('Default value is invalid. Please input number less than maximum 255');
                        }
                        break;
                    case 'decimal':
                        if (trim($size) == '') {
                            $size_array = array(
                                HDTools::lastNumber(14),
                                HDTools::lastNumber(6),
                            );
                        } else {
                            $size_array = explode(',', $field_length);
                            $size_array[0] -= $size_array[1];
                        }
                        if (!Validate::isUnsignedFloat($default)) {
                            $this->errors[] = $this->l('Default value is invalid type decimal');
                        } else {
                            $number_split = explode('.', $default);
                            if ($number_split[0] > (int)$size_array[0]) {
                                $this->errors[] = sprintf($this->l('Error maximum partial int of number is %d'), (int)$size_array[0]);
                            }
                            if (isset($number_split[1]) && $number_split[1] > (int)$size_array[1]) {
                                $this->errors[] = sprintf($this->l('Error maximum partial real of number is %d'), (int)$size_array[1]);
                            }
                        }
                        break;
                    default:
                        if ($size!='' && Tools::strlen($default) > (int)$size) {
                            $this->errors[] = sprintf($this->l('Error maximum %d characters'), $size);
                        }
                        break;
                }
                if($type =='email' && !Validate::isEmail($default))
                {
                    $this->errors[] = $this->l('Default value is invalid');
                }
            }
        }
    }

    /**
     * @param $fields_value
     * @param int $id_lang_default
     * @param array $errors
     */
    public function validateOptionFields($fields_value, $id_lang_default = 0)
    {
        $errors = array();

        if (!isset($this->fields_form_option) ||
            !is_array($this->fields_form_option) ||
            !count($this->fields_form_option) > 0
        ) {
            $this->errors[] = $this->l('Unknown error!');
        } else {
            if ($id_lang_default <= 0) {
                $id_lang_default = (int)Configuration::get('PS_LANG_DEFAULT');
            }
            foreach ($this->fields_form_option as $key => $config) {
                if (isset($config['lang']) && $config['lang']) {
                    if (isset($config['required'])
                        && $config['required']
                        && $config['type'] != 'switch'
                        && isset($fields_value[$key . '_' . $id_lang_default])
                        && trim($fields_value[$key . '_' . $id_lang_default]) == ''
                    ) {
                        $errors[$key . '_' . $id_lang_default] = $config['label'] . ' ' . $this->l('is required');
                    }
                } else {
                    if (isset($config['required'])
                        && $config['required']
                        && $config['type'] != 'switch'
                        && isset($fields_value[$key])
                        && trim($fields_value[$key]) == ''
                    ) {
                        $errors[$key] = $config['label'] . ' ' . $this->l('is required');
                    } elseif (
                        isset($config['regex'])
                        && is_array($config['regex'])
                        && count($config['regex']) > 0
                    ) {
                        foreach ($config['regex'] as $regex) {
                            if (isset($regex['bool'])
                                && isset($regex['pattern'])
                                && trim($regex['pattern']) !== ''
                            ) {
                                if ($regex['bool'] && !preg_match($regex['pattern'], trim($fields_value[$key])) || !$regex['bool'] && preg_match($regex['pattern'], trim($fields_value[$key]))) {
                                    $errors[$key] = $config['label'] . ' ' . (isset($regex['error']) ? $regex['error'] : $this->l('invalid'));
                                }
                            }
                        }
                    } elseif (
                        isset($config['validate'])
                        && method_exists('Validate', $config['validate'])
                        && isset($fields_value[$key])
                        && $fields_value[$key]
                    ) {
                        $validate = $config['validate'];
                        if (!Validate::$validate(trim($fields_value[$key])))
                            $errors[$key] = $config['label'] . ' ' . $this->l('is invalid');
                        unset($validate);
                    } elseif (
                        ($config['type'] !== 'checkbox' || $config['type'] !== 'hidden')
                        && isset($fields_value[$key])
                        && $fields_value[$key]
                        && !Validate::isCleanHtml(trim($fields_value[$key]))
                    ) {
                        $errors[$key] = $config['label'] . ' ' . $this->l('is invalid');
                    }
                }
            }
        }

        return count($errors) > 0 ? $errors : true;
    }

    public function ajaxProcessSave()
    {
        $json_array = array();
        $object = $this->processSave();
        if (!count($this->errors)
            && !count($this->op_errors)
            && Validate::isLoadedObject($object)
        ) {
            $this->object = $object;
            $this->addTicketColumn();
            $json_array = array(
                'msg' => $this->l('Saved'),
                'id' => $this->object->id
            );
            $cache_options = $this->addColumnOptions();
            if (is_array($cache_options) &&
                count($cache_options) > 0
            ) {
                $json_array['cache_options'] = $cache_options;
            }
        }
        $msg_error = count($this->errors) > 0 ? Tools::nl2br(implode(PHP_EOL, $this->errors)) : false;
        $json_array['errors'] = $msg_error;
        $json_array['column'] = !$msg_error && count($this->op_errors) <= 0 ? $this->renderItemColumn() : '';
        $json_array['op_errors'] = count($this->op_errors) > 0 ? $this->op_errors : false;

        $this->ajaxJson($json_array);
    }

    public function processDelete()
    {
        if (Validate::isLoadedObject($object = $this->loadObject())) {
            if (!$object->delete()) {
                $this->errors[] = $this->l('An error occurred during deletion.');
            } elseif (trim($object->name) !== ''
                && in_array($object->name, HDTicket::getSchema())
            ) {
                if (!HDTicket::dropColumn($object->name))
                    $this->errors[] = $this->l('Cannot drop column in table');
            }
        } else {
            $this->errors[] = $this->l('An error occurred while deleting the object.');
        }
    }

    public function ajaxProcessDelete()
    {
        $this->processDelete();
        $msg_error = count($this->errors) > 0 ? Tools::nl2br(implode(PHP_EOL, $this->errors)) : false;
        $this->ajaxJson(array(
            'errors' => $msg_error,
            'msg' => $this->l('Item removed.'),
        ));
    }

    /**
     * Change object position.
     *
     * @return ObjectModel|false
     */
    public function ajaxProcessPosition()
    {
        $itemId = Tools::getValue('itemId');
        $previousId = Tools::getValue('previousId');

        if (trim($itemId) == '' || !Validate::isUnsignedInt($itemId) || $itemId <= 0 || trim($previousId) == '' || !Validate::isUnsignedInt($previousId) || $previousId < 0) {
            $this->errors[] = $this->l('Cannot sort by item.');
        } elseif (!($object = new $this->className($itemId)) || !Validate::isLoadedObject($object)) {
            $this->errors[] = $this->l('Item selected is not found.');
        } elseif (!$object->updatePosition($previousId)) {
            $this->errors[] = $this->l('Sort by item fail.');
        }
        $has_error = count($this->errors) > 0 ? 1 : 0;
        $this->ajaxJson(array(
            'ok' => !$has_error,
            'msg' => $has_error ? implode(PHP_EOL, $this->errors) : $this->l('Sort success')
        ));
    }

    /**
     * Change object position.
     *
     * @return ObjectModel|false
     */
    public function ajaxProcessOptionPosition()
    {
        $itemId = Tools::getValue('itemId');
        $previousId = Tools::getValue('previousId');

        if (trim($itemId) == '' || !Validate::isUnsignedInt($itemId) || $itemId <= 0 || trim($previousId) == '' || !Validate::isUnsignedInt($previousId) || $previousId < 0) {
            $this->errors[] = $this->l('Cannot sort by item.');
        } elseif (!($object = new $this->className($itemId)) || !Validate::isLoadedObject($object)) {
            $this->errors[] = $this->l('Item selected is not found.');
        } elseif (!$object->updatePosition($previousId)) {
            $this->errors[] = $this->l('Sort by item fail.');
        }
        $has_error = count($this->errors) > 0 ? 1 : 0;
        $this->ajaxJson(array(
            'ok' => !$has_error,
            'msg' => $has_error ? implode(PHP_EOL, $this->errors) : $this->l('Sort success')
        ));
    }

    public function ajaxProcessStatus()
    {
        if ($this->loadObject()) {
            $field = trim(Tools::getValue('field'));
            if ($field == '' ||
                !Validate::isCleanHtml($field)
            ) {
                $this->errors[] = $this->l('Field update is invalid.');
            } else {
                $this->object->$field = !$this->object->$field;
                if (!$this->object->update()) {
                    $this->errors[] = $this->l('Update status fail.');
                }
            }
        } else
            $this->errors[] = $this->l('Item doest\'n exist.');

        $has_error = count($this->errors) > 0 ? 1 : 0;
        $this->ajaxJson(array(
            'ok' => !$has_error,
            'errors' => $has_error ? implode(PHP_EOL, $this->errors) : false,
            'msg' => !$has_error ? $this->l('Saved.') : false,
        ));
    }

    public function ajaxProcessClearFiles()
    {
        $ETS_HD_CLEAR_FILE_UPLOAD = trim(Tools::getValue('ETS_HD_CLEAR_FILE_UPLOAD'));
        if ($ETS_HD_CLEAR_FILE_UPLOAD == '') {
            $this->errors[] = $this->l('Clear file upload is required');
        } elseif (
            !Validate::isCleanHtml($ETS_HD_CLEAR_FILE_UPLOAD) ||
            !($option = HDDefines::getInstance()->getOptionTimes($ETS_HD_CLEAR_FILE_UPLOAD))
        ) {
            $this->errors[] = $this->l('Clear file upload is invalid');
        } else {
            $files = HDTools::getRecursiveFiles(rtrim(HDDefines::$default_upload, '/'), $files, isset($option['value']) && $option['value'] > 0 ? $option['value'] : 0);
            if ($files) {
                foreach ($files as $file) {
                    if (isset($file['path']) && @is_writeable($file['path'])) {
                        @unlink($file['path']);
                    }
                }
            }
        }
        $has_error = count($this->errors) > 0 ? 1 : 0;
        $this->ajaxJson(array(
            'ok' => !$has_error,
            'errors' => $has_error ? implode(PHP_EOL, $this->errors) : false,
            'msg' => !$has_error ? $this->l('Saved.') : false,
            'options' => !$has_error ? HDDefines::getInstance()->getOptionTimes(null, false) : false,
        ));
    }
}