<?php

namespace Hura8\Components\Product\Controller;

use Hura8\Components\Product\Model\ProductCollectionModel;
use Hura8\System\Url;
use Hura8\Components\Brand\Model\BrandModel;
use Hura8\Components\Product\AdminController\AProductHotController;
use Hura8\Components\Product\Model\ProductAttributeModel;
use Hura8\Components\Product\Model\ProductAttributeValueModel;
use Hura8\Components\Product\Model\ProductCategoryModel;
use Hura8\Components\Product\Model\ProductFilterModel;
use Hura8\Components\Product\Model\ProductSearchModel;
use Hura8\Interfaces\TableName;
use Hura8\Traits\ClassCacheTrait;


class ProductFilterController
{

    use ClassCacheTrait;

    protected $_request_url = '';

    /* @var ProductFilterModel $objProductFilterModel */
    protected  $objProductFilterModel;

    /*
    all types of filtering representation must be finally translated to this format
    For example:
    - ?brand=sony => translated to brand=>array(2,),
    - ?monitor_size=12inch&color=red => translated to attribute=> array(123, 23121,)
     */
    protected $filters = [
        "price"         => array('max' => 0, 'min'=> 0),
        "brand"         => array(), // array(1,2,3,)
        "collection"    => array(), // array(1,2,3,)
        "supplier"      => array(), // array(1,2,3,)
        "rating"        => array(), // array(1,2,3,)
        "category"      => array(), // array(1,2,3,)
        "status"        => array(),  // array(1,2,3,)
        "query"         => "", // string search keyword
        "hotType"       => array(),// array(saleoff | not | new)
        "attribute"     => array(), // array(1,2,3,)
        "ids"           => array(), // array(1,2,3,)
        "excluded_ids"  => array(), // array(1,2,3,)
        "promotion"     => "",
        "storeId"       => array(), // array(1,2,3,)
        "other_filter"  => array(), // array(in-stock, has-promotion etc...)
        "spec_group_id"       => array(), // array(1,2,3,)
    ];


    public function __construct($request_url = '') {
        $this->_request_url = $request_url;
    }


    public function getResult(
        $current_page_id =1,
        $number_per_page=10,
        $sort_by = 'new',
        array $existing_filters=[],
        $current_category_ids = [],
        $price_range = []
    ) {

        $objProductFilterBuilder = new ProductFilterBuilderController($this->_request_url);
        $built_filters = $objProductFilterBuilder->buildProductFilterFromUrl($existing_filters);
        $this->setFilters($built_filters);

        $product_result = $this->findProductListIdMatchFilters($current_page_id, $number_per_page, $sort_by);
        //debug_var($product_result);

        $objProductFilterOptions = new ProductFilterOptionsController(
            $this->getFilters(),
            $current_category_ids,
            $product_result['item_list'],
            $price_range
        );
        $objProductFilterOptionsTranslation = new ProductFilterOptionsTranslationController($this->_request_url);

        list ( $filter_options, $filter_messages ) = $objProductFilterOptionsTranslation->getAllFilterOptions(
            $objProductFilterOptions->categoryList(),
            $objProductFilterOptions->attributeList(),
            $objProductFilterOptions->brandList(),
            $objProductFilterOptions->priceList()
        );

        return [
            'total'              => $product_result['total'],
            'paged_product_list'  => $product_result['item_list'],
            'filter_options'     => $filter_options,
            'filter_messages'    => $filter_messages,
        ];
    }


    public function getFilters() {
        return $this->filters;
    }


    // allow to update filters
    public function setFilters(array $new_filters) {
        foreach ($new_filters as $key => $value) {
            if(isset($this->filters[$key])) {
                $this->filters[$key] = $value;
            }
        }
    }


    protected function createFilterCacheKey($sort_by) {
        return md5(\json_encode($this->filters) . $sort_by);
    }


    // find a list of products that match filtering conditions
    protected function findProductListIdMatchFilters($current_page_id, $number_per_page, $sort_by = "new" ) {

        $cache_key = $this->createFilterCacheKey($sort_by);

        return self::getCache($cache_key, function () use ($current_page_id, $number_per_page, $sort_by) {
            return $this->findProductListIdMatchFilters_raw($current_page_id, $number_per_page, $sort_by );
        });
    }


    protected function findProductListIdMatchFilters_raw($current_page_id=1, $number_per_page=10, $sort_by = "new" ) {

        list( , , , $where_query ) = $this->buildSQLConditionFromFilters($sort_by);

        $ordering_clause = $this->getOrderingClause($sort_by);

        $objProductFilterModel = new ProductFilterModel();

        list($total_number, $item_list) = $objProductFilterModel->findProductListIdMatchFilters([
                                                                                                    $where_query,
                                                                                                    $current_page_id,
                                                                                                    $number_per_page,
                                                                                                    $ordering_clause
                                                                                                ]);


        $final_result = [
            "total"         => $total_number,
            "item_list"     => $item_list,
        ];

        return $final_result;
    }


    protected function buildSQLConditionFromFilters( $sort_by = "new" ) {
        //list of available filters
        $filterPath = [];
        $filter_messages = [];
        $where_query = [];

        // system controls
        if( ENABLE_PRODUCT_EXPIRE ) {
            $where_query[] = " AND (from_time =0 OR from_time < '".CURRENT_TIME."') 
					           AND (to_time > '".CURRENT_TIME."' OR to_time=0 ) ";
        }

        //other filters
        if( array_key_exists("other_filter", $this->filters) && sizeof($this->filters["other_filter"])) {
            foreach ($this->filters["other_filter"] as $_filter) {
                switch ($_filter) {
                    case "in-stock";
                        $filter_messages[] = [
                            'title' => 'Còn hàng',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND quantity > 0 ";
                        break;
                    case "has-vat";
                        $filter_messages[] = [
                            'title' => 'Có thuế VAT',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `has_vat` = 1 ";
                        break;
                    case "out-stock";
                        $filter_messages[] = [
                            'title' => 'Hết hàng',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `quantity` = 0 ";
                        break;
                    case "has-market-price";
                        $filter_messages[] = [
                            'title' => 'Có giá thị trường',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND market_price > 0 ";
                        break;
                    case "no-price";
                        $filter_messages[] = [
                            'title' => 'Không có giá',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `price` = 0 ";
                        break;
                    case "no-warranty";
                        $filter_messages[] = [
                            'title' => 'Không có bảo hành',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND LENGTH(warranty) < 2 ";
                        break;
                    case "no-sku";
                        $filter_messages[] = [
                            'title' => 'Không mã kho hàng',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND LENGTH(sku) < 2 ";
                        break;
                    case "has-config";
                        $filter_messages[] = [
                            'title' => 'Không có cấu hình',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `config_count` > 0 ";
                        break;
                    case "no-image";
                        $filter_messages[] = [
                            'title' => 'Không có ảnh',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND image_count = 0 ";
                        break;
                    case "no-category";
                        $filter_messages[] = [
                            'title' => 'Không có danh mục',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `category` = '0'  ";
                        break;
                    case "display-off";
                        $filter_messages[] = [
                            'title' => 'Đang ẩn',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `status`=0 ";
                        break;
                    case "display-on";
                        $filter_messages[] = [
                            'title' => 'Đang hiển thị',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND `status`=1 ";
                        break;
                    case "has-promotion":
                        $filter_messages[] = [
                            'title' => 'Có khuyến mại',
                            'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
                        ];
                        $where_query[] = " AND LENGTH(`special_offer`) < 5 ";
                        break;
                    //...add more
                }
            }
        }

        /*// limit by admin permission
        //1-1-2014 gioi han theo san pham danh muc ma quan tri nay quan ly
        global $admin_permission;
        $restricted_category_per_admin = (isset($admin_permission['permit'])) ? $admin_permission['permit']['product:category']['ids'] : [];
        if(sizeof($restricted_category_per_admin)) {
            $cat_query = $this->db->runQuery("
								SELECT DISTINCT pro_id
								FROM ".TB_PRODUCT_CATEGORY."
								WHERE `category_id` IN (".join(",", $restricted_category_per_admin).")
								LIMIT 5000
							");

            //lay danh sach danh muc cua san pham
            $product_in_category = [];
            foreach( $this->db->fetchAll($cat_query) as $cat_info ){
                $product_in_category[] = $cat_info["pro_id"];
            }

            $where_query[] = (sizeof($product_in_category)) ? " AND id IN (". join(',', $product_in_category) .") " : " AND id = 0  ";
        }*/


        //- brand id or ids or brand_indexes
        if( array_key_exists("brand", $this->filters) && sizeof($this->filters["brand"])) {

            $objBrandModel = new BrandModel();

            $condition = array();
            foreach ($this->filters["brand"] as $brand_id) {
                if(!$brand_id) continue;

                $brand_info =  $objBrandModel->getInfo( $brand_id);
                if(!$brand_info) continue;

                $filterPath["brand"][] =  array(
                    "id"   => $brand_info['id'],
                    "name" => $brand_info["title"],
                );

                $condition[] = " brandId = '".intval($brand_info['id'])."' ";
                $filter_messages[] = [
                    'title' => $brand_info['title'],
                    'reset' => Url::buildUrl($this->_request_url, ['brand' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["brand"], $brand_id ))] ),
                ];
            }

            if(sizeof($condition)) {
                $where_query[]  = " AND ( ".join(" OR ", $condition)." )";
            }
        }


        //- collection id or ids
        if( array_key_exists("collection", $this->filters) && sizeof($this->filters["collection"])) {
            $condition = array();

            $objProductCollectionModel = new ProductCollectionModel();

            foreach ($this->filters["collection"] as $_id) {

                $collection_info = $objProductCollectionModel->getInfo($_id);
                if(!$collection_info) continue;

                $filterPath["collection"][] =  array(
                    "id"   => $_id,
                    "name" => $collection_info["title"],
                );
                $condition[] = " `id` IN ( SELECT product_id FROM ".TableName::PRODUCT_PER_COLLECTION." WHERE `collection_id`='".intval($collection_info['id'])."' ) ";
                $filter_messages[] = [
                    'title' => 'Bộ sưu tập ',
                    'reset' => Url::buildUrl($this->_request_url, ['collection' => join(',', remove_item_from_array($this->filters["collection"], $_id))] ),
                ];
            }

            $where_query[] = " AND ( ".join(" OR ", $condition)." )";
        }

        //- supplier id
        if( array_key_exists("supplier", $this->filters) && sizeof($this->filters["supplier"])) {
            /*$condition = array();

            if(!$this->objSupplier) $this->objSupplier = new Supplier();

            foreach ($this->filters["supplier"] as $_id) {
                $_id = intval($_id);

                $supplier_info = $this->objSupplier->getInfo($_id);

                $filterPath["supplier"][] =  array(
                    "id"   => $_id,
                    "name" => $supplier_info["name"],
                );
                $condition[] = " supplier_id = '".$_id."' ";
                $filter_messages[] = [
                    'title' => $supplier_info["name"],
                    'reset' => Url::buildUrl($this->_request_url,  ['supplier' => join(',', remove_item_from_array($this->filters["supplier"], $_id))] ),
                ];
            }

            $where_query[] = " AND ( ".join(" OR ", $condition)." )";*/
        }

        //- rating: 1-> 5
        if( array_key_exists("rating", $this->filters) && sizeof($this->filters["rating"])) {
            $condition = array();
            foreach ($this->filters["rating"] as $_id) {

                $condition[] = " `rating` = '".intval($_id)."' ";
                $filterPath["rating"][] =  array(
                    "id"   => $_id,
                    "name" => $_id,
                );
                $filter_messages[] = [
                    'title' => 'Đánh giá '.$_id,
                    'reset' => Url::buildUrl($this->_request_url, ['rating' => join(',', remove_item_from_array($this->filters["rating"], $_id))] ),
                ];
            }

            $where_query[] = " AND ( ".join(" OR ", $condition)." )";
        }

        //- category id or ids
        if( array_key_exists("category", $this->filters) && sizeof($this->filters["category"])) {

            $objProductCategoryModel = new ProductCategoryModel();

            $condition = array();
            foreach ($this->filters["category"] as $cat_id) {

                $cat_info = $objProductCategoryModel->getInfo($cat_id);
                if(!$cat_info) continue;

                if($cat_info["is_parent"]) {
                    $childListId = ($cat_info["child_ids"]) ?: '0';
                    $condition[] = " `category_id` IN (".$childListId .") ";
                }else{
                    $condition[] = " `category_id` = '".$cat_id."' ";
                }

                $filterPath["category"][] =  array(
                    "id"   => $cat_id,
                    "name" => $cat_info['title'],
                );

                $filter_messages[] = [
                    'title' => $cat_info['title'],
                    'reset' => Url::buildUrl($this->_request_url, ['category' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["category"], $cat_id))] ),
                ];
            }

            if(sizeof($condition)) {
                $where_query[] = " AND `id` IN ( SELECT DISTINCT `item_id` FROM ".TableName::PRODUCT_PER_CATEGORY." WHERE " . join(" OR ", $condition) . " )";
            }
        }

        //- status: 0|1|null
        if( array_key_exists("status", $this->filters) && sizeof($this->filters["status"])) {
            $where_query[] = "  AND `status` IN (".join(',', $this->filters["status"]).") ";
        }

        // spec_group_id
        if( array_key_exists("spec_group_id", $this->filters) && sizeof($this->filters["spec_group_id"])) {
            $where_query[] = "  AND `spec_group_id` IN (".join(',', $this->filters["spec_group_id"]).") ";
        }

        // detail_page_only: 0 | 1
        if( array_key_exists("detail_page_only", $this->filters) && $this->filters["detail_page_only"]) {
            $where_query[] = "  AND `detail_page_only` = '".intval($this->filters['detail_page_only'])."' ";
        }


        //- query: search keyword
        if( array_key_exists("query", $this->filters) && $this->filters["query"]) {
            $keyword_search = $this->filters["query"];
            $search_by_product_id = intval(preg_replace('/[^0-9]/i', '', $keyword_search));

            // todo: add more
            $filter_search = [];
            if(isset($this->filters["brand"]) && $this->filters["brand"]) {
                $filter_search['brand'] = ["IN", $this->filters["brand"]];
            }

            if(isset($this->filters["status"]) && $this->filters["status"]) {
                $filter_search['status'] = ["IN", $this->filters["status"]];
            }

            $objProductSearchModel = new ProductSearchModel();
            $match_result = $objProductSearchModel->find($keyword_search, $filter_search);

            //debug_var($match_result);

            $filterPath["search"] =  array(
                "id"   => $keyword_search,
                "name" => $keyword_search,
            );
            $filter_messages[] = [
                'title' => $keyword_search,
                'reset' => Url::buildUrl($this->_request_url, ['q' => ''] ),
            ];

            if($search_by_product_id > 0) {
                $where_query[] = (sizeof($match_result) > 0) ? " AND ( `id` IN (".join(',', $match_result).") OR `id` = '".$search_by_product_id."' ) " : " AND `id` = '".$search_by_product_id."' ";
            }else{
                $where_query[] = (sizeof($match_result) > 0) ? " AND `id` IN (".join(',', $match_result).")  " : " AND `id` = -1  ";
            }

        }


        //- hotType: saleoff | not | new | or combination of types
        if( array_key_exists("hotType", $this->filters) && sizeof($this->filters["hotType"])) {
            $config_hottype = AProductHotController::getProductHotTypeList();
            $condition = array();
            foreach ($this->filters["hotType"] as $_id) {
                if(!array_key_exists($_id, $config_hottype)) continue;

                $condition[] = " `hot_type` = '".$_id."' ";

                $filter_messages[] = [
                    'title' => $config_hottype[$_id],
                    'reset' => Url::buildUrl($this->_request_url, ['hotType' => '']),
                ];
            }

            if(sizeof($condition)) {
                $where_query[] = " AND `id` IN (SELECT pro_id FROM ".TB_PRODUCT_HOT." WHERE 1 AND ( ".join(" OR ", $condition)." ) ) ";
            }

        }


        //- attribute values
        /*
        if( array_key_exists("attribute", $this->filters) && sizeof($this->filters["attribute"])) {
            $filter_attr_value_list = $this->filters["attribute"];
            //filter = attr_value_1-attr_value_2-attr_value_3,
            $query_attr_id = [];
            $count_filter = 0;

            foreach($filter_attr_value_list as $attr_id){
                $attr_id = (int) $attr_id;
                if($attr_id) {
                    $query_attr_id[] = $attr_id;
                    $count_filter ++;
                }
            }

            $product_filter_id_match = array();
            if(sizeof($query_attr_id)) {
                $query = $this->db->runQuery("
										SELECT DISTINCT pro_id , COUNT(*) as num_pro
										FROM ".TB_PRODUCT_ATTRIBUTE."
										WHERE attr_value_id IN (".join(',', $query_attr_id).")
										GROUP BY pro_id
										HAVING num_pro = ".$count_filter."
										LIMIT 10000
									");
                foreach ( $this->db->fetchAll($query) as $rs ) {
                    $product_filter_id_match[] = $rs["pro_id"];
                }
            }

            $where_query[] = (sizeof($product_filter_id_match)) ? " AND `id` IN (".join(', ', $product_filter_id_match).") " : " AND `id` = 0 " ;

            //xay lai url de back
            if(!$this->objCategoryProduct) $this->objCategoryProduct = new CategoryProduct();

            foreach($filter_attr_value_list as $value_id ){
                $att_name = $this->objCategoryProduct->atrValueName($value_id);

                $filterPath["attribute"][] =  array(
                    "id"   => $value_id,
                    "name" => $att_name,
                );
                $filter_messages[] = [
                    'title' => $att_name,
                    'reset' => Url::buildUrl($this->_request_url, ['filter' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["attribute"], $value_id))] ),
                ];
            }

        }

        */

        //- attribute values
        if( array_key_exists("attribute", $this->filters) && sizeof($this->filters["attribute"])) {

            $filter_attr_value_list = $this->filters["attribute"];

            $attr_values_per_attribute = $this->groupAttributeValuesByAttributeId($filter_attr_value_list);

            $having_match_count = sizeof(array_keys($attr_values_per_attribute));

            $attribute_info_list = $this->groupAttributeListInfo(array_keys($attr_values_per_attribute));

            $attr_where_query = [];
            foreach ($attr_values_per_attribute as $_att_id => $_att_value_list) {
                // if same attribute : find products that match either ONE of these values (not match ALL values)
                $_att_info = $attribute_info_list[$_att_id];
                if (!$_att_info) continue;

                // this attribute requires all products must have ALL selected values
                if ($_att_info['value_match_all'] && sizeof($_att_value_list) > 1) {

                    $_product_id_match_all = $this->getProductMatchAllAttributeValueIds($_att_value_list);

                    if (sizeof($_product_id_match_all) > 0) {
                        $attr_where_query[] = " ( `id` IN (" . join(",", $_product_id_match_all) . ") ) ";
                    } else {
                        $attr_where_query[] = " ( `id` = -1 ) ";
                    }

                } else {
                    $attr_where_query[] = " ( SELECT DISTINCT `pro_id` FROM " . TB_PRODUCT_ATTRIBUTE . " WHERE (" .
                            join(" OR ", array_map(function ($_item) { return " `attr_value_id` = '" . intval($_item['id']) . "' "; }, $_att_value_list))
                        . " ) ) ";
                }

            }

            $product_filter_id_match = array();

            if (sizeof($attr_where_query)) {
                $query = $this->db->runQuery("
                                    SELECT `pro_id` , COUNT(*) AS num_pro
                                    FROM ( " . join(" UNION ALL ", $attr_where_query) . " ) AS tpm_tb
                                    GROUP BY pro_id
                                    HAVING num_pro = " . $having_match_count . "
                                    LIMIT 10000
                                ");
                foreach ($this->db->fetchAll($query) as $rs) {
                    $product_filter_id_match[] = $rs["pro_id"];
                }
            }

            $where_query[] = (sizeof($product_filter_id_match)) ? " AND " . TB_PRODUCT_LIGHT . ".`id` IN (" . join(', ', $product_filter_id_match) . ") " : " AND " . TB_PRODUCT_LIGHT . ".`id` = 0 ";

            //xay lai url de back
            $objProductAttributeModel = new ProductAttributeModel();

            foreach($filter_attr_value_list as $value_id ){
                $att_name = $objProductAttributeModel->getInfo($value_id)['title'];

                $filterPath["attribute"][] =  array(
                    "id"   => $value_id,
                    "name" => $att_name,
                );
                $filter_messages[] = [
                    'title' => $att_name,
                    'reset' => Url::buildUrl($this->_request_url, ['filter' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["attribute"], $value_id))] ),
                ];
            }

            /*//xay lai url de back
            $filterPath["attribute"] = $filter_attr_value_list;

            foreach ($attr_values_per_attribute as $_att_id => $_att_value_list) {
                foreach ($_att_value_list as $_item) {
                    $filter_messages[] = [
                        'title' => $_item['title'],
                        'reset' => Url::buildUrl(CURRENT_URL, ['filter' => join('-', remove_item_from_array($filter_attr_value_list, $_item['id']))]),
                    ];
                }
            }*/

        }


        //given products' ids
        if( array_key_exists("ids", $this->filters) && sizeof($this->filters["ids"])) {

            $filter_messages[] = [
                'title' => "IDs",
                'reset' => Url::buildUrl($this->_request_url, ['ids' => '']),
            ];

            $where_query[] = " AND `id` IN (". join(",", $this->filters["ids"]) .") ";
        }

        // exclude some ids
        if( array_key_exists("excluded_ids", $this->filters) && sizeof($this->filters["excluded_ids"])) {

            $filter_messages[] = [
                'title' => "Excluded IDs",
                'reset' => Url::buildUrl($this->_request_url, ['excluded_ids' => '']),
            ];

            $where_query[] = " AND `id` NOT IN (". join(",", $this->filters["excluded_ids"]) .") ";
        }

        $price_range_query_limit = join(" ",$where_query);

        //- price range
        if(isset($this->filters["price"]) && sizeof($this->filters["price"]) && ($this->filters["price"]['min'] > 0 || $this->filters["price"]['max'] > 0)) {
            //limit by price range
            $maxPrice = clean_price($this->filters["price"]['max']);
            $minPrice = clean_price($this->filters["price"]['min']);

            $price_range_query = '';
            if($maxPrice > 0 && $minPrice > 0){
                $price_range_query = " ( `price` BETWEEN '".$minPrice."' AND '".$maxPrice."'  ) ";

            }else if($maxPrice > 0){
                $price_range_query = " `price` < '".$maxPrice."'   ";

            }else if($minPrice > 0){
                $price_range_query = " `price` >='".$minPrice."' ";
            }

            /*if(ENABLE_INVENTORY_PER_STORE && USER_LOCATION) {

                $list_ids = $this->getProductIds($price_range_query_limit);
                $this->objCache->set("all_product_ids_location", $list_ids);

                $objUStoreLocation = new UStoreLocation();
                $location_products = $objUStoreLocation->getAllProductForLocation(USER_LOCATION, $list_ids, $sort_by);
                $location_products = $this->filterLocationProductByPrice($location_products, $maxPrice, $minPrice);

                $this->objCache->set("location_products", $location_products);

                $location_product_ids = array_keys($location_products);
                $where_query[] = (sizeof($location_product_ids)) ? " AND `id` IN (".join(',', $location_product_ids).") " : " AND `id` = 0";

            } else {
                $where_query[] = " AND ". $price_range_query;
            }*/

            $where_query[] = " AND ". $price_range_query;

            $filterPath["price"] =  array(
                "min" => $minPrice,
                "max" => $maxPrice,
            );

            $price_format = ProductFilterPrice::buildPriceRangeFormat($minPrice, $maxPrice);

            $filter_messages[] = [
                'title' => $price_format['title'],
                'reset' => Url::buildUrl($this->_request_url, ['p' => '', 'min' => '', 'max' => ''])
            ];
        }

        return [
            $price_range_query_limit,
            $filterPath,
            $filter_messages,
            $where_query
        ];
    }


    protected function getProductMatchAllAttributeValueIds(array $_att_value_list) {
        $objProductAttributeModel = new ProductAttributeModel();
        return $objProductAttributeModel->getProductMatchAllAttributeValueIds($_att_value_list);
    }


    protected function groupAttributeListInfo(array $attr_ids) {

        $objProductAttributeModel = new ProductAttributeModel();
        $attr_list_info = $objProductAttributeModel->getListByIds($attr_ids);

        $final_list = [];
        foreach ($attr_ids as $_id) {
            $final_list[$_id] = (isset($attr_list_info[$_id])) ? $attr_list_info[$_id] : null;
        }

        return $final_list;
    }


    protected function groupAttributeValuesByAttributeId(array $attr_value_ids) {

        $objProductAttributeValueModel = new ProductAttributeValueModel(0);

        $result = array();
        foreach ( $objProductAttributeValueModel->getListByIds($attr_value_ids) as $info ) {
            $result[$info['attributeId']][] = [
                'id'    => $info['id'],
                'title' => $info['value'],
            ];
        }

        return $result;
    }


    protected function filterLocationProductByPrice(array $product_list, $max_price, $min_price) {
        if($max_price > 0 && $min_price > 0){
            return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
                return ($pro['price'] >= $min_price && $pro['price'] < $max_price);
            });
        }

        if($max_price > 0){
            return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
                return ($pro['price'] < $max_price);
            });
        }

        if($min_price > 0){
            return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
                return ($pro['price'] >= $min_price);
            });
        }

        return $product_list;
    }


    protected function getOrderingClause($sort_by) {
        $mappings = [
            'order-new'             => "ORDER BY `ordering` DESC, `id` DESC",
            'order-last-update'     => "ORDER BY `ordering` DESC, last_update DESC",
            'last-update'           => "ORDER BY `last_update` DESC",
            'order'                 => "ORDER BY `ordering` DESC",
            'new'                   => "ORDER BY `id` DESC",
            'price-asc'             => "ORDER BY `price` asc",
            'price-desc'            =>  "ORDER BY `price` DESC ",
            'view'                  => "ORDER BY `visit` desc",
            'ranking'               => "ORDER BY `ranking` DESC",
            'name'                  => "ORDER BY `title` asc",
        ];

        if(array_key_exists($sort_by, $mappings)) {
            return $mappings[$sort_by];
        }

        return "ORDER BY `ordering` DESC, `id` DESC";
    }
}
