<?php /** @noinspection PhpMultipleClassDeclarationsInspection */
/*
 *   $Id$
 *
 *   AbanteCart, Ideal OpenSource Ecommerce Solution
 *   http://www.AbanteCart.com
 *
 *   Copyright © 2011-2025 Belavier Commerce LLC
 *
 *   This source file is subject to Open Software License (OSL 3.0)
 *   License details is bundled with this package in the file LICENSE.txt.
 *   It is also available at this URL:
 *   <http://www.opensource.org/licenses/OSL-3.0>
 *
 *  UPGRADE NOTE:
 *    Do not edit or add to this file if you wish to upgrade AbanteCart to newer
 *    versions in the future. If you wish to customize AbanteCart for your
 *    needs please refer to http://www.AbanteCart.com for more information.
 */
if (!defined('DIR_CORE') || !IS_ADMIN) {
    header('Location: static_pages/');
}

class ControllerPagesCatalogProduct extends AController
{
    public $error = [];

    public function main()
    {
        //init controller data
        $this->extensions->hk_InitData($this, __FUNCTION__);

        $this->document->setTitle($this->language->get('heading_title'));

        $this->view->assign('error_warning', $this->session->data['warning']);
        if (isset($this->session->data['warning'])) {
            unset($this->session->data['warning']);
        }
        $this->view->assign('success', $this->session->data['success']);
        if (isset($this->session->data['success'])) {
            unset($this->session->data['success']);
        }

        $this->document->initBreadcrumb(
            [
                'href'      => $this->html->getSecureURL('index/home'),
                'text'      => $this->language->get('text_home'),
                'separator' => false,
            ]
        );

        $grid_settings = [
            'table_id'     => 'product_grid',
            'url'          => $this->html->getSecureURL(
                'listing_grid/product',
                '&' . http_build_query(
                    [
                        'category'     => (int)$this->request->get['category'],
                        'manufacturer' => (int)$this->request->get['manufacturer']
                    ]
                )
            ),
            'editurl'      => $this->html->getSecureURL('listing_grid/product/update'),
            'update_field' => $this->html->getSecureURL('listing_grid/product/update_field'),
            //NOTE: set default sorting by date_modified, but column not present in the grid
            'sortname'     => 'date_modified',
            'sortorder'    => 'desc',
            'actions'      => [
                'edit'     => [
                    'text' => $this->language->get('text_edit'),
                    'href' => $this->html->getSecureURL('catalog/product/update', '&product_id=%ID%'),
                ],
                'save'     => [
                    'text' => $this->language->get('button_save'),
                ],
                'delete'   => [
                    'text' => $this->language->get('button_delete'),
                ],
                'clone'    => [
                    'text' => $this->language->get('text_clone'),
                    'href' => $this->html->getSecureURL('catalog/product/copy', '&product_id=%ID%'),
                ],
                'dropdown' => [
                    'text'     => $this->language->get('text_choose_action'),
                    'href'     => $this->html->getSecureURL('catalog/product/update', '&product_id=%ID%'),
                    'children' => array_merge(
                        [
                            'quickview'  => [
                                'text'  => $this->language->get('text_quick_view'),
                                'href'  => $this->html->getSecureURL(
                                    'catalog/product/update',
                                    '&product_id=%ID%'
                                ),
                                //quick view port URL
                                'vhref' => $this->html->getSecureURL(
                                    'r/common/viewport/modal',
                                    '&viewport_rt=catalog/product/update&product_id=%ID%'
                                ),
                            ],
                            'general'    => [
                                'text' => $this->language->get('tab_general'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product/update',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'media'      => [
                                'text' => $this->language->get('tab_media'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_images',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'options'    => [
                                'text' => $this->language->get('tab_option'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_options',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'files'      => [
                                'text' => $this->language->get('tab_files'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_files',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'relations'  => [
                                'text' => $this->language->get('tab_relations'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_relations',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'promotions' => [
                                'text' => $this->language->get('tab_promotions'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_promotions',
                                    '&product_id=%ID%'
                                ),
                            ],
                            'layout'     => [
                                'text' => $this->language->get('text_design'),
                                'href' => $this->html->getSecureURL(
                                    'catalog/product_layout',
                                    '&product_id=%ID%'
                                ),
                            ],

                        ],
                        (array)$this->data['grid_edit_expand']
                    ),
                ],

            ],
        ];

        $grid_settings['colNames'] = [
            '',
            $this->language->get('column_name'),
            $this->language->get('column_model'),
            $this->language->get('column_sku'),
            $this->language->get('column_price'),
            $this->language->get('column_quantity'),
            $this->language->get('column_status'),
        ];
        $grid_settings['colModel'] = [
            [
                'name'     => 'image',
                'index'    => 'image',
                'align'    => 'center',
                'width'    => 65,
                'sortable' => false,
                'search'   => false,
            ],
            [
                'name'  => 'name',
                'index' => 'name',
                'align' => 'center',
                'width' => 200,
            ],
            [
                'name'  => 'model',
                'index' => 'model',
                'align' => 'center',
                'width' => 90,
            ],
            [
                'name'  => 'sku',
                'index' => 'sku',
                'align' => 'center',
                'width' => 90,
            ],
            [
                'name'   => 'price',
                'index'  => 'price',
                'align'  => 'center',
                'width'  => 80,
                'search' => false,
            ],
            [
                'name'   => 'quantity',
                'index'  => 'quantity',
                'align'  => 'center',
                'width'  => 70,
                'search' => false,
            ],
            [
                'name'   => 'status',
                'index'  => 'status',
                'align'  => 'center',
                'width'  => 70,
                'search' => false,
            ],
        ];

        $form = new AForm();
        $form->setForm(
            [
                'form_name' => 'product_grid_search',
            ]
        );

        //get search filter from cookie if required
        $search_params = [];
        if ($this->request->get['saved_list']) {
            $grid_search_form = json_decode(html_entity_decode($this->request->cookie['grid_search_form']));
            if ($grid_search_form->table_id == $grid_settings['table_id']) {
                parse_str($grid_search_form->params, $search_params);
            }
        }

        $grid_search_form = [];
        $grid_search_form['id'] = 'product_grid_search';
        $grid_search_form['form_open'] = $form->getFieldHtml(
            [
                'type'   => 'form',
                'name'   => 'product_grid_search',
                'action' => '',
            ]
        );
        $grid_search_form['submit'] = $form->getFieldHtml(
            [
                'type'  => 'button',
                'name'  => 'submit',
                'text'  => $this->language->get('button_go'),
                'style' => 'button1',
            ]
        );
        $grid_search_form['reset'] = $form->getFieldHtml(
            [
                'type'  => 'button',
                'name'  => 'reset',
                'text'  => $this->language->get('button_reset'),
                'style' => 'button2',
            ]
        );

        $grid_search_form['fields']['keyword'] = $form->getFieldHtml(
            [
                'type'        => 'input',
                'name'        => 'keyword',
                'value'       => $search_params['keyword'],
                'placeholder' => $this->language->get('filter_product'),
            ]
        );
        $grid_search_form['fields']['match'] = $form->getFieldHtml(
            [
                'type'    => 'selectbox',
                'name'    => 'match',
                'value'   => $search_params['match'],
                'options' => [
                    'any'   => $this->language->get('filter_any_word'),
                    'all'   => $this->language->get('filter_all_words'),
                    'exact' => $this->language->get('filter_exact_match'),
                ],
            ]
        );
        $grid_search_form['fields']['pfrom'] = $form->getFieldHtml(
            [
                'type'        => 'input',
                'name'        => 'pfrom',
                'value'       => $search_params['pfrom'],
                'placeholder' => '0',
                'style'       => 'small-field',
            ]
        );
        $grid_search_form['fields']['pto'] = $form->getFieldHtml(
            [
                'type'        => 'input',
                'name'        => 'pto',
                'value'       => $search_params['pto'],
                'placeholder' => $this->language->get('filter_price_max'),
                'style'       => 'small-field',
            ]
        );

        if ($this->request->get['category']) {
            $search_params['category'] = $this->request->get['category'];
        }

        $this->loadModel('catalog/category');
        $results = $this->model_catalog_category->getCategories(
            0,
            $this->session->data['current_store_id']
        );
        $this->data['categories'] = ['' => $this->language->get('text_select_category')]
            + array_column($results, 'name', 'category_id');

        $grid_search_form['fields']['category'] = $form->getFieldHtml(
            [
                'type'        => 'selectbox',
                'name'        => 'category',
                'options'     => $this->data['categories'],
                'style'       => 'chosen',
                'value'       => $search_params['category'],
                'placeholder' => $this->language->get('text_select_category'),
            ]
        );
        $title = '';
        if ($search_params['category']) {
            $title = $this->data['categories'][$search_params['category']];
        }

        $this->loadModel('catalog/manufacturer');
        $results = $this->model_catalog_manufacturer->getManufacturers(
            ['store_id' => $this->session->data['current_store_id']]
        );
        $this->data['brands'] = ['' => $this->language->get('text_select_brand')]
            + array_column($results, 'name', 'manufacturer_id');

        if ($this->request->get['manufacturer']) {
            $search_params['manufacturer'] = $this->request->get['manufacturer'];
        }

        $grid_search_form['fields']['brand'] = $form->getFieldHtml(
            [
                'type'        => 'selectbox',
                'name'        => 'manufacturer',
                'options'     => $this->data['brands'],
                'style'       => 'chosen',
                'value'       => $search_params['manufacturer'],
                'placeholder' => $this->language->get('text_select_brand'),
            ]
        );
        if ($search_params['manufacturer']) {
            $title .= ($title ? ', ' : '') . $this->data['brands'][$search_params['manufacturer']];
        }

        $this->document->addBreadcrumb(
            [
                'href'      => $this->html->getSecureURL('catalog/product'),
                'text'      => $this->language->get('heading_title', 'catalog/product') . ' ' . ($title ? '(' . $title . ')' : ''),
                'separator' => ' :: ',
                'current'   => true,
            ]
        );

        $grid_search_form['fields']['status'] = $form->getFieldHtml(
            [
                'type'        => 'selectbox',
                'name'        => 'status',
                'value'       => $search_params['status'],
                'placeholder' => $this->language->get('text_select_status'),
                'options'     => [
                    1 => $this->language->get('text_enabled'),
                    0 => $this->language->get('text_disabled'),
                ],
            ]
        );

        $grid_settings['search_form'] = true;

        $grid_settings['multiaction_options'] = [
            'delete'            => $this->language->get('text_delete_selected'),
            'save'              => $this->language->get('text_save_selected'),
            'enable'            => $this->language->get('text_enable_selected'),
            'disable'           => $this->language->get('text_disable_selected'),
            'relate'            => $this->language->get('text_set_related'),
            'create_collection' => $this->language->get('text_create_collection'),
        ];

        $this->view->assign('relate_selected_url', $grid_settings['editurl']);
        $this->view->assign('create_collection_url', $this->html->getSecureURL('catalog/collections/insert'));
        $this->view->assign('text_success_relation_set', $this->language->get('text_success_relation_set'));
        $this->view->assign('text_warning_empty_set', $this->language->get('text_warning_empty_set'));

        $grid = $this->dispatch('common/listing_grid', [$grid_settings]);
        $this->view->assign('listing_grid', $grid->dispatchGetOutput());
        $this->view->assign('search_form', $grid_search_form);
        $this->view->assign('form_language_switch', $this->html->getContentLanguageSwitcher());
        $this->view->assign('form_store_switch', $this->html->getStoreSwitcher());

        $this->view->assign('insert', $this->html->getSecureURL('catalog/product/insert'));
        $this->view->assign('help_url', $this->gen_help_url('product_listing'));
        $this->processTemplate('pages/catalog/product_list.tpl');

        //update controller data
        $this->extensions->hk_UpdateData($this, __FUNCTION__);
    }

    public function insert()
    {
        //init controller data
        $this->extensions->hk_InitData($this, __FUNCTION__);

        if ($this->request->is_POST() && $this->_validateForm()) {
            $product_data = $this->_prepareData($this->request->post);
            $product_id = $this->model_catalog_product->addProduct($product_data);
            $this->data['product_id'] = $product_id;
            $this->model_catalog_product->updateProductLinks($product_id, $product_data);
            $this->extensions->hk_ProcessData($this, 'product_insert');
            $this->session->data['success'] = $this->language->get('text_success');
            redirect($this->html->getSecureURL('catalog/product/update', '&product_id=' . $product_id));
        }
        $this->_getForm();

        //update controller data
        $this->extensions->hk_UpdateData($this, __FUNCTION__);
    }

    public function update(...$args)
    {
        //init controller data
        $this->extensions->hk_InitData($this, __FUNCTION__);

        $this->view->assign('error_warning', $this->session->data['warning']);
        if (isset($this->session->data['warning'])) {
            unset($this->session->data['warning']);
        }
        $this->view->assign('success', $this->session->data['success']);
        if (isset($this->session->data['success'])) {
            unset($this->session->data['success']);
        }

        if ($this->request->is_POST() && $this->_validateForm()) {
            $product_data = $this->_prepareData($this->request->post);
            $product_id = $this->data['product_id'] = (int)$this->request->get['product_id'];
            $this->model_catalog_product->updateProduct($product_id, $product_data);
            $this->model_catalog_product->updateProductLinks($product_id, $product_data);
            $this->extensions->hk_ProcessData($this, 'product_update');
            $this->session->data['success'] = $this->language->get('text_success');
            redirect($this->html->getSecureURL('catalog/product/update', '&product_id=' . $product_id));
        }
        $this->_getForm($args);
        //update controller data
        $this->extensions->hk_UpdateData($this, __FUNCTION__);
    }

    public function copy()
    {
        //init controller data
        $this->extensions->hk_InitData($this, __FUNCTION__);

        $this->document->setTitle($this->language->get('heading_title'));
        if (isset($this->request->get['product_id']) && $this->_validateCopy()) {
            $this->data['new_product'] = $this->model_catalog_product->copyProduct($this->request->get['product_id']);
            $this->extensions->hk_ProcessData($this, 'product_copy');
            if ($this->data['new_product']) {
                $this->session->data['success'] = sprintf(
                    $this->language->get('text_success_copy'),
                    $this->data['new_product']['name']
                );

                if ($this->data['new_product']['layout_clone']) {
                    $this->session->data['success'] .= ' ' . $this->language->get('text_success_copy_layout');
                }
                redirect(
                    $this->html->getSecureURL(
                        'catalog/product/update',
                        '&product_id=' . $this->data['new_product']['id']
                    )
                );
            } else {
                $this->session->data['success'] = $this->language->get('text_error_copy');
                redirect($this->html->getSecureURL('catalog/product'));
            }
        }

        //update controller data
        $this->extensions->hk_UpdateData($this, __FUNCTION__);
    }

    private function _getForm($args = [])
    {
        $productId = null;
        $product_info = [];
        $viewport_mode = $args[0]['viewport_mode'] ?? '';
        $content_language_id = $this->language->getContentLanguageID();
        $history = [];
        if (isset($this->request->get['product_id'])) {
            $productId = (int)$this->request->get['product_id'];
            $history = [
                'table'     => 'product_descriptions',
                'record_id' => $productId,
            ];
            $product_info = $this->model_catalog_product->getProduct($productId);
            $product_info['featured'] = $product_info['featured'] ? 1 : 0;
            $product_info['has_track_options'] = $this->model_catalog_product->hasTrackOptions($productId);
            $product_info['stock_locations'] = $this->model_catalog_product->getProductStockLocations($productId);
            if ($product_info['has_track_options']) {
                $product_info['quantity'] = $this->model_catalog_product->hasAnyStock($productId);
            }
            $this->data['product_description'] = $this->model_catalog_product->getProductDescriptions($productId);
            $title = $this->language->get('text_edit')
                . '&nbsp;'
                . $this->language->get('text_product')
                . ' - '
                . $this->data['product_description'][$content_language_id]['name'];
        } else {
            $title = $this->language->get('text_insert');
        }
        $this->document->setTitle($title);

        $this->data['error'] = $this->error;
        $this->data['cancel'] = $this->html->getSecureURL('catalog/product');

        $this->document->initBreadcrumb(
            [
                'href'      => $this->html->getSecureURL('index/home'),
                'text'      => $this->language->get('text_home'),
                'separator' => false,
            ]
        );
        $this->document->addBreadcrumb(
            [
                'href'      => $this->html->getSecureURL('catalog/product'),
                'text'      => $this->language->get('heading_title'),
                'separator' => false,
            ]
        );
        $this->document->addBreadcrumb(
            [
                'href'      => $this->html->getSecureURL('catalog/product'),
                'text'      => $title,
                'separator' => ' :: ',
                'current'   => true,
            ]
        );

        $this->loadModel('setting/store');
        $this->loadModel('catalog/category');
        $this->data['categories'] = [];

        $product_stores = array_column($this->model_setting_store->getStores(), 'store_id');
        $results = $this->model_catalog_category->getCategories(ROOT_CATEGORY_ID, $product_stores);
        foreach ($results as $r) {
            $name = $r['name'] . (count($product_stores) > 1 ? ' (' . $r['store_name'] . ')' : '');
            $this->data['categories'][$r['category_id']] = $name;
        }

        /** @var ModelSettingStore $mdl */
        $mdl = $this->loadModel('setting/store');
        $this->data['stores'] =
            [0 => $this->language->get('text_default')]
            + array_column($mdl->getStores(), 'name', 'store_id');

        /** @var ModelCatalogManufacturer $mdl */
        $mdl = $this->loadModel('catalog/manufacturer');
        $this->data['manufacturers'] = [0 => $this->language->get('text_none')]
            + array_column($mdl->getManufacturers(), 'name', 'manufacturer_id');

        /** @var ModelLocalisationStockStatus $mdl */
        $mdl = $this->loadModel('localisation/stock_status');
        $this->data['stock_statuses'] =
            ['0' => $this->language->get('text_none')]
            + array_column($mdl->getStockStatuses(), 'name', 'stock_status_id');

        /** @var ModelLocalisationTaxClass $mdl */
        $mdl = $this->loadModel('localisation/tax_class');
        $this->data['tax_classes'] = [0 => $this->language->get('text_none')]
            + array_column($mdl->getTaxClasses(), 'title', 'tax_class_id');

        /** @var ModelLocalisationWeightClass $wMdl */
        $wMdl = $this->loadModel('localisation/weight_class');
        $this->data['weight_classes'] = array_column($wMdl->getWeightClasses(),'title','weight_class_id');

        /** @var ModelLocalisationLengthClass $lenMdl */
        $lenMdl = $this->loadModel('localisation/length_class');
        $this->data['length_classes'] = array_column($lenMdl->getLengthClasses(),'title','length_class_id');

        $fields = array_merge(
            [
                'product_category',
                'featured',
                'product_store',
                'model',
                'call_to_order',
                'sku',
                'location',
                'keyword',
                'image',
                'manufacturer_id',
                'shipping',
                'ship_individually',
                'shipping_price',
                'free_shipping',
                'quantity',
                'minimum',
                'maximum',
                'subtract',
                'sort_order',
                'stock_status_id',
                'stock_checkout',
                'price',
                'cost',
                'status',
                'tax_class_id',
                'weight',
                'weight_class_id',
                'length',
                'width',
                'height',
            ],
            (array)$this->data['form_field_names']
        );

        foreach ($fields as $f) {
            $this->data[$f] = $this->request->post[$f] ?? $product_info[$f];
        }

        if (isset($this->request->post['product_category'])) {
            $this->data['product_category'] = $this->request->post['product_category'];
        } elseif (isset($product_info)) {
            $this->data['product_category'] = $this->model_catalog_product->getProductCategories($productId);
        } else {
            $this->data['product_category'] = [];
        }

        if (isset($this->request->post['product_store'])) {
            $this->data['product_store'] = $this->request->post['product_store'];
        } elseif (isset($product_info)) {
            $this->data['product_store'] = $this->model_catalog_product->getProductStores($productId);
        } else {
            $this->data['product_store'] = [(int)$this->session->data['current_store_id']];
        }

        if (isset($this->request->post['product_description'])) {
            $this->data['product_description'] = $this->request->post['product_description'];
        } elseif (isset($product_info)) {
            $this->data['product_description'] = $this->model_catalog_product->getProductDescriptions(
                $productId,
                $content_language_id
            );
        } else {
            $this->data['product_description'] = [];
        }

        if (isset($this->request->post['featured'])) {
            $this->data['featured'] = $this->request->post['featured'];
        } elseif (isset($product_info)) {
            $this->data['featured'] = $product_info['featured'];
        } else {
            $this->data['featured'] = 0;
        }

        if (isset($this->request->post['product_tags'])) {
            $this->data['product_tags'] = $this->request->post['product_tags'];
        } elseif (isset($product_info)) {
            $this->data['product_tags'] = $this->model_catalog_product->getProductTags(
                $productId,
                $content_language_id
            );
        } else {
            $this->data['product_tags'] = '';
        }

        /** @var ModelToolImage $mdl */
        $mdl = $this->loadModel('tool/image');
        if (isset($product_info) && $product_info['image'] && file_exists(DIR_IMAGE . $product_info['image'])) {
            $preview = $product_info['image'];
        } else {
            $preview = 'no_image.jpg';
        }
        $this->data['preview'] = $mdl->resize($preview, 100, 100);

        if (!isset($this->data['stock_status_id'])) {
            $this->data['stock_status_id'] = $this->config->get('config_stock_status_id');
        }

        $this->data['date_available'] = $this->request->post['date_available']
            ?? $product_info['date_available']
            ?? dateInt2ISO(time() - 86400);

        $weight_info = $wMdl->getWeightClassDescriptionByUnit( $this->config->get('config_weight_class') );
        $this->data['weight_class_id'] = (int)$this->request->post['weight_class_id']
            ?: (int)$product_info['weight_class_id']
            ?: (int)$weight_info['weight_class_id']
            ?: '';

        $length_info = $lenMdl->getLengthClassDescriptionByUnit( $this->config->get('config_length_class') );
        $this->data['length_class_id'] = (int)$this->request->post['length_class_id']
            ?: (int)$product_info['length_class_id'] ?: (int)$length_info['length_class_id'] ?: '';

        $onByDefaults = array_merge(
            [ 'status', 'quantity', 'minimum', 'sort_order' ],
            (array)$this->data['form_fields_on_by_default']
        );
        foreach( $onByDefaults as $onByDefault ) {
            if ($this->data[$onByDefault] === '') {
                $this->data[$onByDefault] = 1;
            }
        }

        $this->data['active'] = 'details';
        if (!isset($productId)) {
            $this->data['action'] = $this->html->getSecureURL('catalog/product/insert');
            $this->data['form_title'] = $this->language->get('text_insert') . $this->language->get('text_product');
            $this->data['update'] = '';
            $form = new AForm('ST');
            $this->data['summary_form'] = '';
        } else {
            $this->data['action'] = $this->html->getSecureURL('catalog/product/update', '&product_id=' . $productId);
            $this->data['form_title'] = $this->language->get('text_edit')
                . '&nbsp;' . $this->language->get('text_product');
            $this->data['update'] = $this->html->getSecureURL('listing_grid/product/update_field', '&id=' . $productId);
            $form = new AForm('HS');

            $this->data['active'] = 'general';
            //load tabs controller
            $tabs_obj = $this->dispatch('pages/catalog/product_tabs', [$this->data]);
            $this->data['product_tabs'] = $tabs_obj->dispatchGetOutput();
            unset($tabs_obj);
            $this->addChild('pages/catalog/product_summary', 'summary_form', 'pages/catalog/product_summary.tpl');
        }

        $form->setForm(
            [
                'form_name' => 'productFrm',
                'update'    => $this->data['update'],
            ]
        );

        $this->data['form']['id'] = 'productFrm';
        $this->data['form']['form_open'] = $form->getFieldHtml(
            [
                'type'   => 'form',
                'name'   => 'productFrm',
                'action' => $this->data['action'],
                'attr'   => 'data-confirm-exit="true" class="aform form-horizontal"',
            ]
        );

        $this->data['form']['submit'] = $form->getFieldHtml(
            [
                'type'  => 'button',
                'name'  => 'submit',
                'text'  => $this->language->get('button_save'),
                'style' => 'button1',
            ]
        );

        $this->data['form']['cancel'] = $form->getFieldHtml(
            [
                'type'  => 'button',
                'name'  => 'cancel',
                'text'  => $this->language->get('button_cancel'),
                'style' => 'button2',
            ]
        );

        $this->data['form']['fields']['general']['status'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'status',
                'value' => $this->data['status'],
                'style' => 'btn_switch btn-group-sm',
            ]
        );

        $this->data['form']['fields']['general']['featured'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'featured',
                'value' => $this->data['featured'],
                'style' => 'btn_switch btn-group-sm',
            ]
        );

        $this->data['form']['fields']['general']['name'] = $form->getFieldHtml(
            [
                'type'         => 'input',
                'name'         => 'product_description[name]',
                'value'        => $this->data['product_description']['name'],
                'required'     => true,
                'multilingual' => true,
                'history'      => $history
            ]
        );

        $this->data['form']['fields']['general']['blurb'] = $form->getFieldHtml(
            [
                'type'         => 'textarea',
                'name'         => 'product_description[blurb]',
                'value'        => $this->data['product_description']['blurb'],
                'multilingual' => true,
                'history'      => $history
            ]
        );

        if ($viewport_mode != 'modal') {
            $this->data['form']['fields']['general']['description'] = $form->getFieldHtml(
                [
                    'type'         => 'texteditor',
                    'name'         => 'product_description[description]',
                    'value'        => $this->data['product_description']['description'],
                    'multilingual' => true,
                    'history'      => $history
                ]
            );
        }

        $this->data['form']['fields']['general']['meta_keywords'] = $form->getFieldHtml(
            [
                'type'         => 'textarea',
                'name'         => 'product_description[meta_keywords]',
                'value'        => $this->data['product_description']['meta_keywords'],
                'multilingual' => true,
                'history'      => $history
            ]
        );

        $this->data['form']['fields']['general']['meta_description'] = $form->getFieldHtml(
            [
                'type'         => 'textarea',
                'name'         => 'product_description[meta_description]',
                'value'        => $this->data['product_description']['meta_description'],
                'multilingual' => true,
                'history'      => $history
            ]
        );

        $this->data['form']['fields']['general']['tags'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'product_tags',
                'value' => $this->data['product_tags'],
            ]
        );

        $this->data['form']['fields']['general']['category'] = $form->getFieldHtml(
            [
                'type'        => 'checkboxgroup',
                'name'        => 'product_category[]',
                'value'       => $this->data['product_category'],
                'options'     => $this->data['categories'],
                'style'       => 'chosen',
                'placeholder' => $this->language->get('text_select_category'),
            ]
        );

        $this->data['form']['fields']['general']['store'] = $form->getFieldHtml(
            [
                'type'        => 'checkboxgroup',
                'name'        => 'product_store[]',
                // if new product - take selected store from storeSwitcher
                //otherwise - take product data
                'value'       => $productId
                    ? $this->data['product_store']
                    : ($this->data['product_store'] ?: [$this->config->get('current_store_id')]),
                'options'     => $this->data['stores'],
                'style'       => 'chosen',
                'placeholder' => $this->language->get('entry_store'),
            ]
        );

        $this->data['form']['fields']['data']['manufacturer'] = $form->getFieldHtml(
            [
                'type'        => 'selectbox',
                'name'        => 'manufacturer_id',
                'value'       => $this->data['manufacturer_id'],
                'options'     => $this->data['manufacturers'],
                'style'       => 'chosen',
                'placeholder' => $this->language->get('entry_manufacturer'),
            ]
        );

        $this->data['form']['fields']['data']['model'] = $form->getFieldHtml(
            [
                'type'     => 'input',
                'name'     => 'model',
                'value'    => $this->data['model'],
                'required' => false,
            ]
        );

        $this->data['form']['fields']['data']['call_to_order'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'call_to_order',
                'value' => $this->data['call_to_order'],
                'style' => 'btn_switch btn-group-sm',
            ]
        );

        $this->data['currency'] = $this->currency->getCurrency($this->config->get('config_currency'));
        $this->data['form']['fields']['data']['price'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'price',
                'value' => moneyDisplayFormat($this->data['price']),
            ]
        );
        $this->data['form']['tax_selector'] = $form->getFieldHtml(
            [
                'type'    => 'selectbox',
                'name'    => 'tax_selector',
                'value'   => $this->data['tax_class_id'] ?? $this->config->get('config_tax_class_id'),
                'options' => $this->data['tax_classes'],
                'style'   => 'no-save'
            ]
        );
        $this->data['entry_tax_rule'] =
            $this->html->buildElement(
                [
                    'type'   => "button",
                    'href'   => $this->html->getSecureURL('localisation/tax_class'),
                    'text'   => $this->language->get('entry_tax_rule'),
                    'target' => '_blank',
                    'style'  => ' '
                ]
            );

        $this->data['entry_price_with_tax'] = $this->language->get('entry_price_with_tax');
        $this->data['form']['price_with_tax'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'price_with_tax',
                'value' => '',
                'style' => 'no-save',
            ]
        );
        $this->data['price_calc_url'] = $this->html->getSecureURL('r/product/product/getTaxPrice');
        $this->data['form']['fields']['data']['cost'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'cost',
                'value' => moneyDisplayFormat($this->data['cost']),
                'style' => 'small-field',
            ]
        );

        $this->data['form']['fields']['data']['tax_class'] = $form->getFieldHtml(
            [
                'type'     => 'selectbox',
                'name'     => 'tax_class_id',
                'value'    => $this->data['tax_class_id'] ?? $this->config->get('config_tax_class_id'),
                'options'  => $this->data['tax_classes'],
                'help_url' => $this->gen_help_url('tax_class'),
                'style'    => 'medium-field',
            ]
        );
        $this->data['form']['fields']['data']['subtract'] = $form->getFieldHtml(
            [
                'type'     => 'selectbox',
                'name'     => 'subtract',
                'value'    => $this->data['subtract'],
                'options'  => [
                    1 => $this->language->get('text_yes'),
                    0 => $this->language->get('text_no'),
                ],
                'help_url' => $this->gen_help_url('product_inventory'),
                'style'    => 'medium-field',
                'attr'     => 'reload_on_save="true" ',
                'disabled' => $product_info['has_track_options'],
            ]
        );

        $this->data['form']['fields']['data']['quantity'] = $form->getFieldHtml(
            [
                'type'     => 'input',
                'name'     => 'quantity',
                'value'    => (int)$this->data['quantity'],
                'style'    => 'col-xs-1 small-field',
                'help_url' => $this->gen_help_url('product_inventory'),
                'attr'     => ($product_info['has_track_options'] || $product_info['stock_locations']
                    ? 'disabled'
                    : ''),
            ]
        );

        if ($this->data['subtract'] && !$product_info['has_track_options']) {
            $dd = new ADispatcher('responses/product/product/stockLocations', [$product_info['product_id']]);
            $this->data['form']['fields']['data']['stock_locations'] = $dd->dispatchGetOutput(
                'responses/product/product/stockLocations'
            );
        }

        $this->data['form']['fields']['data']['minimum'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'minimum',
                'value' => (int)$this->data['minimum'],
                'style' => 'small-field',
            ]
        );

        $this->data['form']['fields']['data']['maximum'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'maximum',
                'value' => (int)$this->data['maximum'],
                'style' => 'small-field',
            ]
        );

        $this->data['stock_checkout'] = (string)$this->data['stock_checkout'];
        $this->data['stock_checkout'] = $this->data['stock_checkout'] !== ''
            ? (int)$this->data['stock_checkout']
            : $this->data['stock_checkout'];
        $this->data['form']['fields']['data']['stock_checkout'] = $form->getFieldHtml(
            [
                'type'    => 'selectbox',
                'name'    => 'stock_checkout',
                'value'   => $this->data['stock_checkout'],
                'options' => [
                    '' => $this->language->get('text_default'),
                    0  => $this->language->get('text_no'),
                    1  => $this->language->get('text_yes'),
                ],
                'style'   => 'small-field',
            ]
        );

        $this->data['form']['fields']['data']['stock_status'] = $form->getFieldHtml(
            [
                'type'     => 'selectbox',
                'name'     => 'stock_status_id',
                'value'    => (int)($this->data['stock_status_id'] ?: $this->config->get('config_stock_status_id')),
                'options'  => $this->data['stock_statuses'],
                'help_url' => $this->gen_help_url('product_inventory'),
                'style'    => 'small-field',
            ]
        );

        $this->data['form']['fields']['data']['sku'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'sku',
                'value' => $this->data['sku'],
            ]
        );

        $this->data['form']['fields']['data']['location'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'location',
                'value' => $this->data['location'],
            ]
        );
        //prepend button to generate keyword
        $this->data['keyword_button'] = $form->getFieldHtml(
            [
                'type'  => 'button',
                'name'  => 'generate_seo_keyword',
                'text'  => $this->language->get('button_generate'),
                //set button not to submit a form
                'attr'  => 'type="button"',
                'style' => 'btn btn-info',
            ]
        );
        $this->data['generate_seo_url'] = $this->html->getSecureURL(
            'common/common/getseokeyword',
            '&object_key_name=product_id&id=' . $productId
        );

        $this->data['form']['fields']['data']['keyword'] = $form->getFieldHtml(
            [
                'type'         => 'input',
                'name'         => 'keyword',
                'value'        => $this->data['keyword'],
                'help_url'     => $this->gen_help_url('seo_keyword'),
                'attr'         => ' gen-value="' . SEOEncode($this->data['product_description']['name']) . '" ',
                'multilingual' => true,
            ]
        );
        $this->data['form']['fields']['data']['date_available'] = $form->getFieldHtml(
            [
                'type'       => 'date',
                'name'       => 'date_available',
                'value'      => dateISO2Display(
                    $this->data['date_available'],
                    $this->language->get('date_format_short')
                ),
                'default'    => dateNowDisplay(),
                'dateformat' => format4Datepicker($this->language->get('date_format_short')),
            ]
        );

        $this->data['form']['fields']['data']['sort_order'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'sort_order',
                'value' => $this->data['sort_order'],
                'style' => 'tiny-field',
            ]
        );

        $this->data['form']['fields']['data']['shipping'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'shipping',
                'style' => 'btn_switch btn-group-sm',
                'value' => $this->data['shipping'] ?? 1,
            ]
        );

        $this->data['form']['fields']['data']['free_shipping'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'free_shipping',
                'style' => 'btn_switch btn-group-sm',
                'value' => $this->data['free_shipping'] ?? 0,
            ]
        );

        $this->data['form']['fields']['data']['ship_individually'] = $form->getFieldHtml(
            [
                'type'  => 'checkbox',
                'name'  => 'ship_individually',
                'style' => 'btn_switch btn-group-sm',
                'value' => $this->data['ship_individually'] ?? 0,
            ]
        );

        $this->data['form']['fields']['data']['shipping_price'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'shipping_price',
                'value' => moneyDisplayFormat($this->data['shipping_price']),
                'style' => 'tiny-field',
            ]
        );

        $this->data['form']['fields']['data']['length'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'length',
                'value' => $this->data['length'],
                'style' => 'tiny-field',
            ]
        );
        $this->data['form']['fields']['data']['width'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'width',
                'value' => $this->data['width'],
                'attr'  => ' autocomplete="false"',
                'style' => 'tiny-field',
            ]
        );
        $this->data['form']['fields']['data']['height'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'height',
                'value' => $this->data['height'],
                'attr'  => ' autocomplete="false"',
                'style' => 'tiny-field',
            ]
        );

        if ($productId && !$this->data['length_class_id']) {
            $this->data['length_classes'][0] = $this->language->get('text_none');
        }

        $this->data['form']['fields']['data']['length_class'] = $form->getFieldHtml(
            [
                'type'    => 'selectbox',
                'name'    => 'length_class_id',
                'value'   => $this->data['length_class_id'],
                'options' => $this->data['length_classes'],
                'style'   => 'small-field',
            ]
        );

        if ( $productId
            && $this->data['shipping']
            && (!(float)$this->data['weight'] || !$this->data['weight_class_id'])
            && !(float)$this->data['shipping_price']
        ) {
            if (!$this->data['weight_class_id']) {
                $this->data['error']['weight_class'] = $this->language->get('error_weight_class');
            }
            if (!(float)$this->data['weight']) {
                $this->data['error']['weight'] = $this->language->get('error_weight_value');
            }
        }

        if ($productId
            && (!$this->data['weight_class_id']
                || !$this->data['weight_classes'][$this->data['weight_class_id']])
        ) {
            $this->data['weight_classes'][0] = $this->language->get('text_none');
            $this->data['weight_class_id'] = 0;
        }

        $this->data['form']['fields']['data']['weight'] = $form->getFieldHtml(
            [
                'type'  => 'input',
                'name'  => 'weight',
                'value' => $this->data['weight'],
                'attr'  => ' autocomplete="false"',
                'style' => 'tiny-field',
            ]
        );

        $this->data['form']['fields']['data']['weight_class'] = $form->getFieldHtml(
            [
                'type'    => 'selectbox',
                'name'    => 'weight_class_id',
                'value'   => $this->data['weight_class_id'],
                'options' => $this->data['weight_classes'],
                'style'   => 'small-field',
            ]
        );

        $this->data['product_id'] = $productId;
        if ($productId && $this->config->get('config_embed_status')) {
            $btnData = getEmbedButtonsData(
                'common/do_embed/product',
                ['product_id' => $productId],
                $this->data['product_store']
            );
            $this->data['embed_url'] = $btnData['embed_url'];
            $this->data['embed_stores'] = $btnData['embed_stores'];
        }

        $this->data['text_clone'] = $this->language->get('text_clone');
        $this->data['clone_url'] = $this->html->getSecureURL(
            'catalog/product/copy',
            '&product_id=' . $this->request->get['product_id']
        );
        $this->data['form_language_switch'] = $this->html->getContentLanguageSwitcher();
        $this->data['language_id'] = $content_language_id;
        $this->data['language_code'] = $this->session->data['language'];
        $this->data['help_url'] = $this->gen_help_url('product_edit');
        $this->data['list_url'] = $this->html->getSecureURL('catalog/product', '&saved_list=product_grid');

        if ($viewport_mode == 'modal') {
            $tpl = 'responses/viewport/modal/catalog/product_form.tpl';
        } else {
            $this->addChild(
                'responses/common/resource_library/get_resources_html', 'resources_html',
                'responses/common/resource_library_scripts.tpl'
            );
            $resources_scripts = $this->dispatch(
                'responses/common/resource_library/get_resources_scripts',
                [
                    'object_name' => '',
                    'object_id'   => '',
                    'types'       => ['image'],
                ]
            );
            $this->data['resources_scripts'] = $resources_scripts->dispatchGetOutput();
            $this->data['rl'] = $this->html->getSecureURL(
                'common/resource_library',
                '&action=list_library&object_name=&object_id&type=image&mode=single'
            );
            $tpl = 'pages/catalog/product_form.tpl';
        }

        $this->view->batchAssign($this->data);
        $this->processTemplate($tpl);
    }

    protected function _validateForm()
    {
        if (!$this->user->canModify('catalog/product')) {
            $this->error['warning'] = $this->language->get_error('error_permission');
        }
        $post = $this->request->post;
        $productId = $this->request->get['product_id'];
        $len = mb_strlen($post['product_description']['name']);
        if ($len < 1 || $len > 255) {
            $this->error['name'] = $this->language->get_error('error_name');
        }

        if (mb_strlen($post['sku']) > 64) {
            $this->error['sku'] = $this->language->get_error('error_sku');
        }
        if (mb_strlen($post['model']) > 64) {
            $this->error['model'] = $this->language->get_error('error_model');
        }

        $error_text = $this->html->isSEOkeywordExists(
            'product_id=' . $productId,
            $post['keyword']
        );

        if ($error_text) {
            $this->error['keyword'] = $error_text;
        }

        foreach (['length', 'width', 'height', 'weight'] as $name) {
            $v = abs(preformatFloat($post[$name], $this->language->get('decimal_point')));
            if ($v >= 1000) {
                $this->error[$name] = $this->language->get('error_measure_value');
            } elseif ($post['shipping'] && !$v
                && ((float)$post['length'] + (float)$post['width'] + (float)$post['height'])
            ) {
                $this->error[$name] = $this->language->get('error_dimension_value');
            }
        }

        if (!$post['length_class_id'] && $post['shipping']) {
            $this->error['length_class'] = $this->language->get('error_length_class');
        }
        if (!$post['weight_class_id'] && $post['shipping']) {
            $this->error['weight_class'] = $this->language->get('error_weight_class');
        }

        $this->extensions->hk_ValidateData($this, [__FUNCTION__]);

        if (!$this->error) {
            return true;
        } else {
            if (!isset($this->error['warning'])) {
                $this->error['warning'] = $this->language->get_error('error_required_data');
            }
            return false;
        }
    }

    protected function _validateCopy()
    {
        if (!$this->user->canModify('catalog/product')) {
            $this->error['warning'] = $this->language->get_error('error_permission');
        }

        $this->extensions->hk_ValidateData($this, [__FUNCTION__]);
        return (!$this->error);
    }

    protected function _prepareData($data = [])
    {
        if ($data['date_available']) {
            $data['date_available'] = dateDisplay2ISO(
                $data['date_available'],
                $this->language->get('date_format_short')
            );
        }
        //set default store if not set
        $data['product_store'] = $data['product_store'] ?? [0];
        $data['product_category'] = $data['product_category'] ?? [];
        return $data;
    }
}