/**
* Catalog front class
*/
(function (root) {

    "use strict";

    /**
     * Common object params
     * @type {Object}
     */
    var common = {
            publicMethods: ['getRecentlyViewed', 'getCart', 'addToCart', 'lessFromCart', 'removeFromCart', 'clearCart', 'incrementCartItem', 'decrementCartItem', 'infotip', 'updateElements', 'calculateDelivery', 'popupNotFound', 'getItem', 'numberFormat'],
            className: 'Catalog'
        },

        /**
         * Main constructor
         * @return {Object} - this handle
         */
        Protected = function () {

            var self = this;
            document.addEventListener('DOMContentLoaded', this.init.bind(this));
            return this;
        };


    /**
     * Main prototype
     * @type {Object}
     */
    Protected.prototype = {


        init: function () {

            var self = this;

            Observer.subscribe('loadPage', function () {
                self.setEvents();
                self.updateElements();
            });

            // buy event
            document.addEventListener('click', function (event) {

                var selectors = document.querySelectorAll('.buy[data-item-id]'),
                    element = event.target,
                    index = -1;

                if (selectors) {

                    while (element && ((index = Array.prototype.indexOf.call(selectors, element)) === -1)) {
                        element = element.parentElement;
                    }

                    if (index > -1) {
                        (function () {
                            
                           // new JsSplash('Корзина временно недоступна. Вы можете скачать прайс на главной странице и отправить заявку по почте');
                           // return;

                            var itemId = parseInt(this.getAttribute('data-item-id'), 10),
                                params = JSON.parse(this.getAttribute('data-item-params') || '{}');
                            

                            
                            Catalog.infotip(Language.get('Catalog', 'added_into_cart'));
                            Core.ajax('/catalog/cart-action/add/' + itemId + '/', function () {
                                Observer.fire('CatalogAddToCart', itemId);
                                Core.startSynch();
                            });
                            return;
                           

                            //Catalog.addToCart(itemId, params);
                        }).call(element, event);
                    }
                }
            });






            Observer.subscribe('synch', function (response) {

                response = response.Catalog || null;

                try {
                    var resObj = JSON.parse(response);
                } catch (e) {
                    console.error('Catalog. Failed to parse synch data json');
                    return;
                }



                if (!!resObj.recentlyViewedHtml) {
                    var container = document.querySelector('.recently-viewed-items-container'),
                        itemsList = container && container.querySelector('.recently-viewed-items-list'),
                        itemsCount;

                    if (container && itemsList) {
                        itemsList.innerHTML = resObj.recentlyViewedHtml;
                        itemsCount = itemsList.querySelectorAll('.item').length;

                        new JsSimpleSlider('.recently-viewed-list', {
                            itemsPerViewport: Math.min(itemsCount, 2),
                            slidesToScroll: Math.min(itemsCount, 2),
                            cssClasses: {
                                controls: {
                                    prev: 'js-simple-slider-btn js-simple-slider-btn-prev fa fa-angle-left',
                                    next: 'js-simple-slider-btn js-simple-slider-btn-next fa fa-angle-right'
                                }
                            }
                        }, function () {
                            container.classList.remove('-hidden');
                        });
                       
                    }
                    
                }

            

                // update cart
                !!resObj.cart && self.setCart(resObj.cart);

            });

        },


        ucFirst: function (string) {
            return string.charAt(0).toUpperCase() + string.slice(1);
        },


        /**
         * Set events to this module.
         * This code fire methods by 'data-action' attribute of '.catalog-module-action' element 
         */
        setEvents: function () {

            // get action element
            var action = document.querySelector('.catalog-module-action');

            if (action) {

                // try to get attribute
                action = 'action' + this.ucFirst(action.getAttribute('data-action'));

                // fire event action
                this[action] && this[action]();
            }


            this.filterEvents();

            // cart link
            [].forEach.call(document.querySelectorAll('.cart-link'), function (link) {
                link.href = '/catalog/cart/' + Core.uniqid() + '/';
            });


            // stycky cart
            function getElemOffset (obj) {
                var curleft = 0,
                    curtop = 0;
                
                if (obj.offsetParent) {
                    while (1) {
                        curleft += obj.offsetLeft;
                        curtop += obj.offsetTop;
                        if (!obj.offsetParent) {
                            break;
                        }
                        obj=obj.offsetParent;
                    }
                } else if (obj.x || obj.y) {
                    curleft += obj.x;
                    curtop += obj.y;
                }

                return {x: curleft, y: curtop};
            }

            var elem = document.querySelector('.to-sticky'),
                elemOffset = elem && getElemOffset(elem),
                stickTop = 60,
                stickStartOffsetTop = 200;

            if (elem) {
                window.addEventListener('scroll', function () {
                    
                    if (!Catalog.getCart().itemsCount) {
                        return;
                    }

                    var doc = document.documentElement,
                        left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
                        top = (window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0);

                    if (top > (elemOffset.y - stickTop + stickStartOffsetTop)) {
                        if (!elem.classList.contains('stick')) {
                            elem.classList.add('stick');
                            elem.style.position = 'fixed';
                            elem.style.top = stickTop + 'px';
                            elem.style.left = elemOffset.x + 'px';
                            elem.style.zIndex = 100;
                        }

                    } else {
                        elem.classList.remove('stick');
                        elem.style.position = '';
                        elem.style.top = '';
                        elem.style.left = '';
                        elem.style.zIndex = '';
                    }

                });
            }

            document.querySelector('.cart').addEventListener('click', function () {
                (this.tagName !== 'A') && Core.loadPage(this.querySelector('.order').href);
            });



            // image title
            [].forEach.call(document.querySelectorAll('.catalog img[title]'), function (elem) {
                elem.setAttribute('title', '');
            });




            // quick search
            [].forEach.call(document.querySelectorAll('input[name="quicksearch"]'), function (inputSearch) {

                var searchBtn = inputSearch.parentNode.querySelector('.search-go');

                searchBtn.addEventListener('click', function () {

                    var searchStr = inputSearch.value.toLowerCase(),
                        searchWords = searchStr.trim().split(' '),
                        data = {
                            filter: {
                                search: searchStr
                            }
                        },
                        newData = {
                            filter: {}
                        };


                    // search props
                    [].forEach.call(searchWords, function (word) {

                        word.match(/[0-9]+/gi) && (function () {

                            [].forEach.call(word.match(/[0-9]+/gi), function (price) {
                                if (price.length > 2) {
                                    
                                    newData = {
                                        filter: {
                                            'price-min': '0.00',
                                            'price-max': price + '.00'
                                        }
                                    };

                                    data = Core.mergeObjects(data, newData);
                                }
                            });
                        }());

                    });
 
                    Core.loadPage('/catalog/?' + decodeURIComponent(Core.serialize(data)));
                });

                inputSearch.addEventListener('keypress', function (e) {

                    if (e.keyCode === 13) {
                        var evt = document.createEvent('MouseEvents');
                        evt.initEvent('click', true, true);
                        searchBtn.dispatchEvent(evt);
                    }
                });
            });







        },




        popupNotFound: function () {

            var self = this;

            Core.ajax('/catalog/get-popup-not-found/', function (json) {
                try {
                    var resObj = JSON.parse(json);
                } catch (e) {
                    return;
                }



                self.notFoundPopup = new JsSplash(resObj.html, {cssClass: 'not-found-popup', closeOutClick:false}, function () {
                    var formHandle = document.querySelector('form[name="popupNotFound"]');

                    new Validator(formHandle, function (err, res) {

                        var formData = form2object(formHandle, '.', false);
                        Core.blockScreen();

                        Core.ajax('/catalog/send-not-found-popup/', formData, function (json) {
                            Core.unblockScreen();
                            self.notFoundPopup && self.notFoundPopup.close();
                            
                            try {
                                var resObj = JSON.parse(json);
                            } catch (e) {
                                return;
                            }

                            Core.messageBox(resObj.message);
                        });
                    });
                });
            });

            
        },




        filterEvents: function () {


            // filter trigger
            [].forEach.call(document.querySelectorAll('.catalog-filter-trigger'), function (trigger) {
                trigger.addEventListener('click', function () {
                    this.classList.toggle('-opened');
                });
            });


            [].forEach.call(document.querySelectorAll('form[name="catalogFilter"]'), function (formHandle) {
                //Core.loadScript('/modules/Catalog/public/front/js/extended/nouislider.js', function () {

                    var rangeSlider = formHandle.querySelector('.price-range-slider'),
                        rangeMinInput = rangeSlider && formHandle.querySelector('[name="filter.price-min"]'),
                        rangeMaxInput = rangeSlider && formHandle.querySelector('[name="filter.price-max"]'),
                        min = rangeSlider && parseInt(rangeSlider.getAttribute('data-min'), 10),
                        max = rangeSlider && parseInt(rangeSlider.getAttribute('data-max'), 10),
                        currentMin = rangeMinInput && parseInt(rangeMinInput.value, 10),
                        currentMax = rangeMinInput && parseInt(rangeMaxInput.value, 10);

                    if (rangeSlider) {

                        var rangeSliderMarkerMin = formHandle.querySelector('.price-range-marker .marker-min'),
                            rangeSliderMarkerMax = formHandle.querySelector('.price-range-marker .marker-max');


                        currentMax = (currentMax <= max && currentMax > currentMin) ? currentMax : max;
                        currentMin = (currentMin >= min && currentMin < currentMax) ? currentMin : min;

                        // setup range slider
                        noUiSlider.create(rangeSlider, {
                            start: [currentMin, currentMax],
                            connect: true,
                            margin: 100,
                            step: 10,
                            range: {
                                min: min,
                                max: max
                            }
                        });

                        // range slider onUpdate event
                        rangeSlider.noUiSlider.on('update', function (data) {
                            rangeMinInput.value = data[0];
                            rangeMaxInput.value = data[1];

                            rangeSliderMarkerMin && (rangeSliderMarkerMin.innerHTML = data[0]);
                            rangeSliderMarkerMax && (rangeSliderMarkerMax.innerHTML = data[1]);
                        });

                        // change price input event
                        rangeMinInput.addEventListener('change', function () {
                            var value = parseInt(this.value, 10);

                            value = isNaN(value) ? min : value;
                            // update slider
                            rangeSlider.noUiSlider.set([value]);
                            
                            // update input
                            this.value = value;
                        });

                        // change price input event
                        rangeMaxInput.addEventListener('change', function () {
                            var value = parseInt(this.value, 10);

                            value = isNaN(value) ? max : value;

                            // update slider
                            rangeSlider.noUiSlider.set([null, value]);

                            // update input
                            this.value = value;
                        });
                    }

                    // Submit event
                    formHandle.addEventListener('submit', function (e) {
                        e.preventDefault();

                        var formData = form2object(this, '.', true),
                            url = '/catalog/?' + decodeURIComponent(Core.serialize(formData));
                        
                        Observer.fire('CatalogFilter', (formData.filter || formData));

                        Core.loadPage(url);
                    });


                    // Submit event
                    formHandle.querySelector('.search-go') && formHandle.querySelector('.search-go').addEventListener('click', function (e) {

                        e.preventDefault();

                        var evt = document.createEvent('MouseEvents');
                        evt.initEvent('click', true, true);
                        formHandle.querySelector('input[type="submit"]').dispatchEvent(evt);
                    });


                    

                    // reset button
                    formHandle.querySelector('input[type="reset"]') && formHandle.querySelector('input[type="reset"]').addEventListener('click', function (e) {
                        e.preventDefault();

                        // reset price sort buttons
                        [].forEach.call(formHandle.querySelectorAll('.price-radios input[type="radio"]'), function (radio, index) {
                            radio.checked = index === 0 ? true : false;
                        });


                        // reset colors checkboxes
                        [].forEach.call(formHandle.querySelectorAll('.color-box input[type="checkbox"]'), function (checkbox) {
                            checkbox.checked = false;
                        });

                        // reset size checkboxes
                        [].forEach.call(formHandle.querySelectorAll('.size-box input[type="checkbox"]'), function (checkbox) {
                            checkbox.checked = false;
                        });

                        // reset categories checkboxes
                        [].forEach.call(formHandle.querySelectorAll('.categories-inputs input[type="checkbox"]'), function (checkbox) {
                            checkbox.checked = false;
                        });

                        // reset tags checkboxes
                        [].forEach.call(formHandle.querySelectorAll('.tags-inputs input[type="checkbox"]'), function (checkbox) {
                            checkbox.checked = false;
                        });

                        // reset brands checkboxes
                        [].forEach.call(formHandle.querySelectorAll('.brands-inputs input[type="checkbox"]'), function (checkbox) {
                            checkbox.checked = false;
                        });

                        formHandle.querySelector('.search-input') && (formHandle.querySelector('.search-input').value = '');

                        // reset select boxes
                        [].forEach.call(formHandle.querySelectorAll('select'), function (selectBox) {
                            selectBox.value = '';
                        });

                        // reset price range slider
                        rangeSlider && rangeSlider.noUiSlider.set([min, max]);
                    });


                    // show more button
                   /* formHandle.querySelector('.show-more') && formHandle.querySelector('.show-more').addEventListener('click', function () {
                        document.querySelector('.catalog-filter-container').classList.toggle('-addon-filter');
                    });*/
                //});

            });



            


            // flip trigger
            var itemsList = document.querySelector('.catalog .items-list');

            itemsList && [].forEach.call(itemsList.querySelectorAll('.item-flipper-trigger[data-item-id]'), function (trigger) {
               
                trigger.addEventListener('click', function (e) {

                    var itemContainer = itemsList.querySelector('.item-wrapper[data-item-id="' + this.getAttribute('data-item-id') + '"]'),
                        itemUrl = itemContainer.querySelector('.item-name[href]').getAttribute('href'),
                        itemImagesContainer = itemContainer.querySelector('.images-block'),
                        itemImagesCollection = itemImagesContainer.querySelectorAll('.images-block img');



                    // remove flip class from other items
                    !this.classList.contains('unflip-trigger') && [].forEach.call(itemsList.querySelectorAll('.item-wrapper.active-flip'), function (elem) {
                        elem.classList.remove('active-flip');
                    });


                    // active flip class
                    itemContainer.classList.toggle('active-flip');

                    if (!itemImagesContainer.classList.contains('-ready')) {

                        // show images
                        [].forEach.call(itemImagesCollection, function (image, index) {

                            if (index === 0) {
                                image.classList.add('active-image');
                            }

                            // preload image
                            var newImg = new Image();
                            newImg.onload = function(){
                                image.style.backgroundImage = 'url("' + this.src + '")';
                                Core.delay(1000, function () {
                                    image.classList.add('-loaded');
                                });
                            }
                            newImg.src = image.getAttribute('data-src');
                        });

                        new JsSimpleSlider(itemImagesContainer, {
                            itemsPerViewport: 1,
                            slidesToScroll: 1,
                            speed: 500,
                            cssClasses: {
                                controls: {
                                    prev: 'js-simple-slider-btn js-simple-slider-btn-prev fa fa-chevron-left',
                                    next: 'js-simple-slider-btn js-simple-slider-btn-next fa fa-chevron-right'
                                }
                            }
                        }, function () {
                            itemImagesContainer.classList.add('-ready');
                            this.roll.addEventListener('click', function () {
                                Core.loadPage(itemUrl);
                            });
                        });
                    }
                    
                });
            });
            
        },



        actionCartPage: function () {



            var self = this,
                formHandle = document.querySelector('.cart-order-form'),
                itemsTable = document.querySelector('.cart-items-list-table'),
                recalculateTableFn,
                validatorOpt = {
                showErrors: false,
                onAir: false,
                rules: {
                        accept: function (value) {
                            return !!value;
                        }
                    },
                    messages: {
                        ru: {
                            accept: {
                                empty: Language.get('Catalog', 'not_accept_oferta')
                            }
                        }
                    }
                };

            new Validator(formHandle, function (err, res) {

                var errLabel,
                    formData,
                    n;

                formData = form2object(formHandle, '.', true);

                [].forEach.call(formHandle.querySelectorAll('.validation-error'), function (errLabel) {
                    errLabel.classList.remove('-visible');
                    errLabel.parentNode.querySelector('input.error') && errLabel.parentNode.querySelector('input.error').classList.remove('error');
                });

                if (err) {
                    for (n in err) {
                        errLabel = formHandle.querySelector('.validation-error[data-field-name="' + err[n].name + '"]');
                        errLabel.classList.add('-visible');
                        errLabel.innerHTML = err[n].errorText;
                        formHandle.querySelector('input[name="' + err[n].name + '"]').classList.add('error');
                    }


                    if ((window.innerWidth || document.body.clientWidth) <= 1024) {

                        new JsScroller({offset: -120}).scrollTo(formHandle.querySelector('.validation-error.-visible'));

                    } else {
                        new JsScroller({offset: -10}).scrollTo(formHandle.querySelector('.validation-error.-visible'));
                    }
                   

                    return;
                }




                // send request
                Core.blockScreen();
                Core.ajax('/catalog/order/create/', formData, function (json) {

                    Core.unblockScreen();
                    try {
                        var resObj = JSON.parse(json);
                    } catch (e) {
                        Core.messageBox('Error');
                        return;
                    }

                   

                    Observer.fire('CatalogCreateOrder', resObj);
                    Catalog.clearCart();

                    if (resObj.payment_url) {

                        Core.confirmBox(Language.get('Catalog', 'order_go_pay_confirm'), function () {
                            location.href = resObj.payment_url;
                            
                        });

                        return;
                    }


                    Core.messageBox(resObj.message, function () {
                        Core.loadPage(resObj.location);
                    });
                   
                });


            }, validatorOpt);


            recalculateTableFn = function () {


                
                Core.blockScreen();

                Core.ajax('/catalog/cart-action/0/0/', function (json) {
                   
                    Core.unblockScreen();
                    try {
                        var cart = JSON.parse(json);
                    } catch (e) {
                        console.error('Failed to parse response');
                        return;
                    }
                    
                    var allItemsCountElem = document.querySelector('[data-type="cart-all-items-count"]'),
                    allProductsCountElem = document.querySelector('[data-type="cart-all-products-count"]'),
                    totalCostElem = document.querySelector('[data-type="cart-total-cost"]'),
                    totalCost = 0,
                    allItemsCount = 0,
                    allProductsCount = 0;


                    if (!itemsTable) {
                        return;
                    }

                    [].forEach.call(itemsTable.querySelectorAll('tbody tr[data-item-uniq]'), function (tr) {
                        
                        var itemUniq = tr.getAttribute('data-item-uniq'),
                            countElem = tr.querySelector('[data-type="cart-item-count"][data-item-uniq="' + itemUniq + '"]'),
                            costElem = tr.querySelector('[data-type="cart-item-cost"][data-item-uniq="' + itemUniq + '"]'),
                            itemPrice = costElem.getAttribute('data-item-price').replace(/\s/, ''),
                            itemMinValue = costElem.getAttribute('data-item-min-value'),
                            itemCount,
                            itemCost;

                        // calculate item count
                        itemCount = cart.items[itemUniq] ? cart.items[itemUniq].count : 0;

                        // calculate item cost
                        itemCost = (parseFloat(itemPrice) * parseInt(itemCount, 10) * parseFloat(itemMinValue)).toFixed(2);

                        // calculate all items count
                        allItemsCount += itemCount;

                        // calculate all products count
                        allProductsCount += 1;

                        // calculate total cost
                        totalCost = (parseFloat(totalCost) + parseFloat(itemCost)).toFixed(2);





                        // set item count
                        countElem.innerHTML = itemCount;

                        // set item cost
                        costElem.innerHTML = Catalog.numberFormat(itemCost, 2, '.', ' ');


                        // set disabled arrows
                        if (parseInt(itemCount, 10) === 1) {
                            tr.querySelector('.less-item[data-item-uniq="' + itemUniq + '"]').classList.add('-disabled');
                        } else {
                            tr.querySelector('.less-item[data-item-uniq="' + itemUniq + '"]').classList.remove('-disabled');
                        }

                    });

                    // set total count of items
                    allItemsCountElem.innerHTML = allItemsCount;

                    // set total count of products
                    allProductsCountElem.innerHTML = allProductsCount;

                    // set total cost
                    totalCostElem.innerHTML = Catalog.numberFormat(totalCost, 2, '.', ' ');
                    
                    (allProductsCount === 0) && Core.loadPage('/catalog/cart/' + Core.uniqid() + '/');
                });

                    
            











                /*var self = this,
                    cart = self.getCart(),
                    allItemsCountElem = document.querySelector('[data-type="cart-all-items-count"]'),
                    allProductsCountElem = document.querySelector('[data-type="cart-all-products-count"]'),
                    totalCostElem = document.querySelector('[data-type="cart-total-cost"]'),
                    totalCost = 0,
                    allItemsCount = 0,
                    allProductsCount = 0;

                if (!itemsTable) {
                    return;
                }


                [].forEach.call(itemsTable.querySelectorAll('tbody tr[data-item-uniq]'), function (tr) {
                    
                    var itemUniq = tr.getAttribute('data-item-uniq'),
                        countElem = tr.querySelector('[data-type="cart-item-count"][data-item-uniq="' + itemUniq + '"]'),
                        costElem = tr.querySelector('[data-type="cart-item-cost"][data-item-uniq="' + itemUniq + '"]'),
                        itemPrice = costElem.getAttribute('data-item-price').replace(/\s/, ''),
                        itemMinValue = costElem.getAttribute('data-item-min-value'),
                        itemCount,
                        itemCost;

                    // calculate item count
                    itemCount = cart.items[itemUniq] ? cart.items[itemUniq].count : 0;

                    // calculate item cost
                    itemCost = (parseFloat(itemPrice) * parseInt(itemCount, 10) * parseFloat(itemMinValue)).toFixed(2);

                    // calculate all items count
                    allItemsCount += itemCount;

                    // calculate all products count
                    allProductsCount += 1;

                    // calculate total cost
                    totalCost = (parseFloat(totalCost) + parseFloat(itemCost)).toFixed(2);





                    // set item count
                    countElem.innerHTML = itemCount;

                    // set item cost
                    costElem.innerHTML = self.numberFormat(itemCost, 2, '.', ' ');


                    // set disabled arrows
                    if (parseInt(itemCount, 10) === 1) {
                        tr.querySelector('.less-item[data-item-uniq="' + itemUniq + '"]').classList.add('-disabled');
                    } else {
                        tr.querySelector('.less-item[data-item-uniq="' + itemUniq + '"]').classList.remove('-disabled');
                    }

                });

                // set total count of items
                allItemsCountElem.innerHTML = allItemsCount;

                // set total count of products
                allProductsCountElem.innerHTML = allProductsCount;

                // set total cost
                totalCostElem.innerHTML = self.numberFormat(totalCost, 2, '.', ' ');
                
                // set disabled to delete buttons
                //(allProductsCount === 1) && itemsTable.querySelector('.remove-item').classList.add('-disabled');

                //(allProductsCount > 1) && itemsTable.querySelector('.remove-item.-disabled') && itemsTable.querySelector('.remove-item.-disabled').classList.remove('-disabled');

                (allProductsCount === 0) && Core.loadPage('/catalog/cart/' + Core.uniqid() + '/');*/

            }




            // arraws up and down
            itemsTable && [].forEach.call(itemsTable.querySelectorAll('.item-count-arrow'), function (elem) {

                elem.addEventListener('click', function () {

                    if (this.classList.contains('-disabled')) {
                        return;
                    }


                    var itemUniq = this.getAttribute('data-item-uniq');

                    switch (true) {
                        case this.classList.contains('more-item'):
                            Core.ajax('/catalog/cart-action/increment/' + itemUniq + '/');
                            self.incrementCartItem(itemUniq);
                        break;

                        case this.classList.contains('less-item'):
                            Core.ajax('/catalog/cart-action/decrement/' + itemUniq + '/');
                            self.decrementCartItem(itemUniq);
                        break;
                    }

                    recalculateTableFn.call(self);
                });
            });


            // remove item buttons
            itemsTable && [].forEach.call(itemsTable.querySelectorAll('.remove-item'), function (elem) {

                elem.addEventListener('click', function () {

                    if (this.classList.contains('-disabled')) {
                        return;
                    }

                    var itemUniq = this.getAttribute('data-item-uniq'),
                        removedTrElem = itemsTable.querySelector('tr[data-item-uniq="' + itemUniq + '"]');

                    Core.ajax('/catalog/cart-action/remove/' + itemUniq + '/');
                    removedTrElem.classList.add('-removed');
                    // delay for animation
                    Core.delay(500, function () {
                        removedTrElem.parentNode.removeChild(removedTrElem);
                        recalculateTableFn.call(self);
                    });

                    /*self.removeFromCart(itemUniq);
                    removedTrElem.classList.add('-removed');
                    
                    // delay for animation
                    Core.delay(500, function () {
                        removedTrElem.parentNode.removeChild(removedTrElem);
                        recalculateTableFn.call(self);
                    });*/
                   
                });
            });


            



            var recalculateDeliveryFn = function () {

                if (!document.querySelector('.cart-order-form')) {
                    return;
                }

                var cost = parseFloat(Catalog.getCart().cost).toFixed(2),
                    orderForm = document.querySelector('.cart-order-form'),
                    delivery = Catalog.calculateDelivery(orderForm.querySelector('#delivery_city').value),
                    finalCost = 0;

                finalCost = (parseFloat(cost) + parseFloat(delivery)).toFixed(2);

                [].forEach.call(orderForm.querySelectorAll('[data-type="catalog-delivery-cost"]'), function (elem) {
                    elem.innerHTML = self.numberFormat(delivery, 2, '.', ' ');
                });
                
                [].forEach.call(orderForm.querySelectorAll('[data-type="catalog-delivery-cost-currency"]'), function (elem) {
                    elem.innerHTML = self.declOfNum(delivery, Language.get('Catalog', 'currency_decl').split(','));
                });

                [].forEach.call(orderForm.querySelectorAll('[data-type="catalog-final-cost"]'), function (elem) {
                    elem.innerHTML = self.numberFormat(finalCost, 2, '.', ' ');
                });
                
                [].forEach.call(orderForm.querySelectorAll('[data-type="catalog-final-cost-currency"]'), function (elem) {
                    elem.innerHTML = self.declOfNum(finalCost, Language.get('Catalog', 'currency_decl').split(','));
                });
            }

            // select city
            formHandle && formHandle.querySelector('#delivery_city').addEventListener('change', function () {
                recalculateDeliveryFn.call(self);
            });

            Observer.subscribe('CatalogCartUpdated', function () {
                recalculateDeliveryFn.call(self);
            });


            // select region
            formHandle && formHandle.querySelector('#delivery_region').addEventListener('change', function () {

                var selectCity = formHandle.querySelector('#delivery_city');

                selectCity.setAttribute('disabled', 'disabled');
                Core.ajax('/catalog/getCity/' + this.value + '/', function (json) {

                    try {
                        var resObj = JSON.parse(json),
                            option,
                            fragment = document.createDocumentFragment(),
                            n;
                    } catch (e) {
                        Core.messageBox('Error');
                        return;
                    }

                    selectCity.innerHTML = '';
                    for (n in resObj) {
                        option = document.createElement('option');
                        option.value = resObj[n].city_id;
                        option.innerHTML = resObj[n].city_name;
                        fragment.appendChild(option);
                    }
                    selectCity.appendChild(fragment);
                    selectCity.removeAttribute('disabled');

                    recalculateDeliveryFn.call(self);
                }); 
            });

            








            // oferta popup
            /*formHandle && formHandle.querySelector('.cart-order-oferta-show').addEventListener('click', function () {

                Core.blockScreen();
                Core.ajax('/catalog/get-oferta/', function (json) {
                    try {
                        var resObj = JSON.parse(json);
                    } catch (e) {
                        Core.messageBox('Error');
                        return;
                    }

                    new JsSplash(resObj.html, {cssClass: 'catalog-oferta'});
                    Core.unblockScreen();
                });
            });*/


            // delivery info
            formHandle && [].forEach.call(formHandle.querySelectorAll('.delivery-info-container'), function (container) {
                container.querySelector('.delivery-info-trigger').addEventListener('click', function () {
                    container.classList.toggle('-closed');
                });
            });


            // recalculate cart table
            itemsTable && recalculateTableFn.call(self);

            formHandle && recalculateDeliveryFn.call(self);

            Observer.fire('CatalogCartPage');
        },



        actionMainPage: function () {

        },


        actionItemPage: function () {

            var self = this,
                mainImage = document.querySelector('.catalog .item-main-image img'),
                otherImagesContainer = document.querySelector('.catalog .item-other-images-container'),
                tabs = document.querySelector('.catalog .catalog-tabs');


            //mainImage && mainImage.setAttribute('alt', '');


            // images
            /* mainImage && new JsViewer(document.querySelectorAll('.catalog-item-page .item-data .item-image img'), {
                leftRightBtns: true,
                infoBlock: true,
                infoTitleAttribute: 'data-external'
            }); */

            /*mainImage && mainImage.addEventListener('click', function () {
                new JsViewer(document.querySelectorAll('.item-image img'), {
                    leftRightBtns: true,
                    infoBlock: false
                });
            });*/

            // other images
            otherImagesContainer && (function () {
                
            	[].forEach.call(otherImagesContainer.querySelectorAll('img'), function (elem) {

                    // preload image
                    self.preloadImages([elem.getAttribute('data-src')]);

                    var imagePseudo = document.createElement('div');
                    imagePseudo.style.position = 'absolute';
                    imagePseudo.style.left = '0';
                    imagePseudo.style.top = '0';
                    imagePseudo.style.width = '100%';
                    imagePseudo.style.height = '100%';

                    elem.parentNode.appendChild(imagePseudo);

                    // click event
                    imagePseudo.addEventListener('click', function () {
                        var src = this.parentNode.querySelector('img').getAttribute('data-src');
                        mainImage.setAttribute('data-src', src);
                        mainImage.setAttribute('src', src);
                    }, false);
            	});


                new JsSimpleSlider(otherImagesContainer, {
                    slidesToScroll: Math.floor(otherImagesContainer.clientWidth / otherImagesContainer.querySelector('.image-wrapper').clientWidth),
                    cssClasses: {
                        controls: {
                            prev: 'js-simple-slider-btn js-simple-slider-btn-prev fa fa-angle-left',
                            next: 'js-simple-slider-btn js-simple-slider-btn-next fa fa-angle-right'
                        }
                    }
                }, function () {
                    otherImagesContainer.classList.remove('-hidden');
                });

 
            }());


            // select color
            [].forEach.call(document.querySelectorAll('.item-colors .item-color'), function (elem) {
                elem.addEventListener('click', function () {

                    var buyBtn = document.querySelector('.item-data .buy[data-item-id]'),
                        params;

                    if (buyBtn) {

                        params = buyBtn.getAttribute('data-item-params') || '{}';
                        params = JSON.parse(params);

                    } else {
                        params = {};
                    }


                    document.querySelector('.item-colors .item-color.active') && (document.querySelector('.item-colors .item-color.active').classList.remove('active'));
                    this.classList.add('active');
                    
                    params.color = this.getAttribute('data-color-name');
                    document.querySelector('.item-data .buy[data-item-id]').setAttribute('data-item-params', JSON.stringify(params));

                });
            });



            // select size
            [].forEach.call(document.querySelectorAll('.item-sizes .item-size'), function (elem) {
                elem.addEventListener('click', function () {

                    var buyBtn = document.querySelector('.item-data .buy[data-item-id]'),
                        params;

                    if (buyBtn) {

                        params = buyBtn.getAttribute('data-item-params') || '{}';
                        params = JSON.parse(params);

                    } else {
                        params = {};
                    }

                    document.querySelector('.item-sizes .item-size.active') && (document.querySelector('.item-sizes .item-size.active').classList.remove('active'));
                    this.classList.add('active');
                    
                    params.size = this.getAttribute('data-size-name');
                    document.querySelector('.item-data .buy[data-item-id]').setAttribute('data-item-params', JSON.stringify(params));

                });
            });

            // prepare images and analogue items init
            this.prepareImages(this.analogueItemsInit);
        },


        actionCategoryPage: function () {

        },



        analogueItemsInit: function () {
            
            /*var container = document.querySelector('.item-other-images-container'),
                items = container && container.querySelectorAll('.image-wrapper');

            container && new JsSimpleSlider(container, {
                slidesToScroll: 1,
                cssClasses: {
                    controls: {
                        prev: 'js-simple-slider-btn js-simple-slider-btn-prev fa fa-angle-left',
                        next: 'js-simple-slider-btn js-simple-slider-btn-next fa fa-angle-right'
                    }
                }
            }, function () {
                container.classList.remove('-hidden');
            });*/
        },


        prepareImages: function (callback) {
            var images = document.querySelectorAll('.catalog img');
            images.length && this.preloadImages(images, callback);
        },

        preloadImages: function (images, callback) {

            images = images.length ? images : [images];

            var currentCount = 0,
                allCount = images.length;


            [].forEach.call(images, function (image, index) {

                //create new image
                (function (img, src) {

                    var newImg = new Image();
                    (typeof img !== 'string') && img.classList.add('-loading');
                    newImg.src = src;

                    //onload event
                    newImg.onload = function(){

                        (typeof img !== 'string') && img.classList.remove('-loading');
                        currentCount += 1;

                        if (currentCount === allCount) {
                            currentCount = null;
                            allCount = null;

                            //run callback in main context
                            callback && callback.apply(this, [img, this.src]);
                            return;
                        }
                    }

                    newImg = null;

                }(image, ((typeof image === 'string') ? image: image.getAttribute('src'))));
            });
        },


        getCart: function () {

            var cart,
                defaultCartObject = {
                    items: {},
                    cost: 0
                },
                n;

            cart = (Cookie.get('catalogCart')) ? JSON.parse(Cookie.get('catalogCart')) : defaultCartObject;

            // array to object conversion
            if(Object.prototype.toString.call(cart.items) === '[object Array]') {
                cart.items = {};
            }

            for (n in cart.items) {

                // array to object conversion
                if(cart.items[n].params && Object.prototype.toString.call(cart.items[n].params) === '[object Array]') {
                    cart.items[n].params = {};
                }
            }

            return cart;
        },


        setCart: function (cartData) {
            Cookie.set('catalogCart', JSON.stringify(cartData), {path: '/', expires: 1000 * 60 * 60 * 24});
            Observer.fire('CatalogCartUpdated');
            this.updateElements();
        },



        getRecentlyViewed: function () {
            var recentlyViewed = Cookie.get('catalogRW') || '[]';
            return JSON.parse(recentlyViewed);
        },


        updateElements: function() {

            var self = this,
                cart = this.getCart(),
                allItemsCount = 0,
                n;

            
            Core.ajax('/catalog/cart-action/0/0/', function (json) {
                try {
                    var cart = JSON.parse(json);
                } catch (e) {
                    console.error('Failed to parse response');
                    return;
                }
                
                [].forEach.call(document.querySelectorAll('.buy[data-item-id]'), function (elem) {
                    elem.classList.remove('-in-cart');
                });

                // update buy buttons
                if (cart.items) {

                    for (n in cart.items) {

                        // increment all items count
                        allItemsCount += (cart.items[n] && cart.items[n].count) ? cart.items[n].count : 1;

                        // mark buy buttons
                        [].forEach.call(document.querySelectorAll('.buy[data-item-id="' + n + '"]'), function (elem) {
                            elem.classList.add('-in-cart');
                        });
                    }
                }



                // set items count
                [].forEach.call(document.querySelectorAll('[data-type="catalog-items-count"]'), function (elem) {
                    elem.innerHTML = allItemsCount > 0 ? allItemsCount : '';
                });

                // set items count word
                [].forEach.call(document.querySelectorAll('[data-type="catalog-items-count-word"]'), function (elem) {
                    elem.innerHTML = allItemsCount > 0 ? self.declOfNum(allItemsCount, Language.get('Catalog', 'item_decl').split(',')) : '';
                });

                // set items cost
                [].forEach.call(document.querySelectorAll('[data-type="catalog-cost"]'), function (elem) {
                    elem.innerHTML = cart.cost > 0 ? self.numberFormat(cart.cost, 2, '.', ' ') : '';
                });

                // set items currency
                [].forEach.call(document.querySelectorAll('[data-type="catalog-cost-currency"]'), function (elem) {
                    elem.innerHTML = cart.cost > 0 ? self.declOfNum(cart.cost, Language.get('Catalog', 'currency_decl').split(',')) : '';
                });

                // set items currency
                [].forEach.call(document.querySelectorAll('.cart-block'), function (elem) {
                    elem.setAttribute('data-items-count', allItemsCount);
                });
            });

             
            


            /*[].forEach.call(document.querySelectorAll('.buy[data-item-id]'), function (elem) {
                elem.classList.remove('-in-cart');
            });

            // update buy buttons
            if (cart.items) {




                for (n in cart.items) {

                    // increment all items count
                    allItemsCount += (cart.items[n] && cart.items[n].count) ? cart.items[n].count : 1;

                    // mark buy buttons
                    [].forEach.call(document.querySelectorAll('.buy[data-item-id="' + n + '"]'), function (elem) {
                        elem.classList.add('-in-cart');
                    });
                }
            }



            // set items count
            [].forEach.call(document.querySelectorAll('[data-type="catalog-items-count"]'), function (elem) {
                elem.innerHTML = allItemsCount > 0 ? allItemsCount : '';
            });

            // set items count word
            [].forEach.call(document.querySelectorAll('[data-type="catalog-items-count-word"]'), function (elem) {
                elem.innerHTML = allItemsCount > 0 ? self.declOfNum(allItemsCount, Language.get('Catalog', 'item_decl').split(',')) : '';
            });

            // set items cost
            [].forEach.call(document.querySelectorAll('[data-type="catalog-cost"]'), function (elem) {
                elem.innerHTML = cart.cost > 0 ? self.numberFormat(cart.cost, 2, '.', ' ') : '';
            });

            // set items currency
            [].forEach.call(document.querySelectorAll('[data-type="catalog-cost-currency"]'), function (elem) {
                elem.innerHTML = cart.cost > 0 ? self.declOfNum(cart.cost, Language.get('Catalog', 'currency_decl').split(',')) : '';
            });

            // set items currency
            [].forEach.call(document.querySelectorAll('.cart-block'), function (elem) {
                elem.setAttribute('data-items-count', allItemsCount);
            });*/

        },


        calculateDelivery: function (cityId) {
            
            return 0;

            cityId = parseInt(cityId, 10);

            var cost = parseFloat(Catalog.getCart().cost).toFixed(2),
                delivery = 0;

            switch (cityId) {

                case 5106: // Ekaterinburg
                    delivery = (cost >= 2500) ? 0 : 250; 
                break;

                case 5095: // V.Pishma
                case 5091: // Berezovskiy
                case 5142: // Sredneuralsk
                    delivery = cost >= parseFloat(5000) ? 0 : 350;                        
                break;

                default:
                    delivery = 1000;
                break;
            }

            return parseFloat(delivery).toFixed(2);
        },


        addToCart: function (itemId, params) {

            params = params || {};

            var cart = this.getCart(),
                uniqId = Core.uniqid(),
                paramsAsString = JSON.stringify(params),
                isNewFlag = true,
                n;

            // search item
            for (n in cart.items) {
                isNewFlag = true;

                // check to params
                if (itemId === cart.items[n].id && paramsAsString === JSON.stringify(cart.items[n].params)) {

                    // increment count or set as 1
                    cart.items[n].count = (cart.items[n].count + 1 || 1);

                    isNewFlag = false;
                    break;

                }
            }


            // if is new item
            if (isNewFlag) {
                cart.items[uniqId] = {
                    id: itemId,
                    params: params,
                    count: 1,
                    price: 0
                }
            }

            this.setCart(cart);
            this.infotip(Language.get('Catalog', 'added_into_cart'));
            Core.startSynch();
            Observer.fire('CatalogAddToCart', itemId);
        },


        lessFromCart: function (itemId, params) {

            params = params || {};

            var cart = this.getCart(),
                paramsAsString = JSON.stringify(params),
                n;

            // search item
            for (n in cart.items) {

                // check to params
                if (itemId === cart.items[n].id && paramsAsString === JSON.stringify(cart.items[n].params)) {
                    
                    // decrement item count
                    cart.items[n].count -= 1;

                    // check item counter as zero
                    if (!cart.items[n].count) {
                        this.removeFromCart(n);
                        return;
                    }

                    break;
                }

            }

            this.setCart(cart);
            Core.startSynch();
        },


        incrementCartItem: function (itemUniqId) {




            var cart = this.getCart();

            if (itemUniqId in cart.items) {
                cart.items[itemUniqId].count += 1;
            }

            this.setCart(cart);
            Core.startSynch();
        },

        decrementCartItem: function (itemUniqId) {

            var cart = this.getCart();

            if (itemUniqId in cart.items) {
                cart.items[itemUniqId].count -= 1;

                if (!cart.items[itemUniqId].count) {
                    this.removeFromCart(itemUniqId);
                    return;
                }
            }

            this.setCart(cart);
            Core.startSynch();
        },

        removeFromCart: function (itemUniqId) {

            var cart = this.getCart(),
                itemId;

            cart.items = cart.items || {};
            itemId = cart.items[itemUniqId].id;

            delete cart.items[itemUniqId];
            this.setCart(cart);

            Core.startSynch();
            Observer.fire('CatalogRemoveFromCart', itemId);
        },

        clearCart: function () {
            var cart = this.getCart();

            cart.items = {};
            cart.cost = 0;
            
            this.setCart(cart);
            Core.startSynch();
            Observer.fire('CatalogClearCart');
        },



        getItem: function (itemId, callback) {

            Core.ajax('/catalog/getItems-data-by-id/' + itemId + '/', function (json) {

                try {
                    var resObj = JSON.parse(json);
                } catch (e) {
                    return;
                }

                callback && callback(resObj);
            });
        },



        infotip: function (message) {

            var tipWrapper = document.createElement('div'),
                tipContainer= document.createElement('div'),
                tip = document.createElement('div');

            tipWrapper.setAttribute('class', 'catalog-infotip-wrapper');
            tipContainer.setAttribute('class', 'catalog-infotip-container');
            tip.setAttribute('class', 'catalog-infotip');

            tip.innerHTML = message;

            tipWrapper.appendChild(tipContainer);
            tipContainer.appendChild(tip);
            document.body.appendChild(tipWrapper);
            

            tipWrapper.addEventListener('click', function () {
                this.classList.remove('-visible');
                Core.loadPage('/catalog/cart/' + Core.uniqid() + '/');
            });

            Core.delay(100, function () {
                tipWrapper && tipWrapper.classList.add('-visible');
            });
            
           
            Core.delay(5000, function () {
                tipWrapper && tipWrapper.classList.remove('-visible');
                Core.delay(800, function () {
                    tipWrapper && tipWrapper.parentNode && tipWrapper.parentNode.removeChild(tipWrapper);
                });
            });
        },

        declOfNum: function(number, titles){  
            number = Math.trunc(number);
            var cases = [2, 0, 1, 1, 1, 2];  
            return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];  
        },

        numberFormat: function(number, decimals, dec_point, thousands_sep) {
            number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
            
            var n = !isFinite(+number) ? 0 : +number,
                prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
                sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
                dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
                s = '',
            
                toFixedFix = function (n, prec){
                    var k = Math.pow(10, prec);
                    return '' + Math.round(n * k) / k;
                };

            s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
            
            if (s[0].length > 3) {
                s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
            }
            
            if ((s[1] || '').length < prec) {
                s[1] = s[1] || '';
                s[1] += new Array(prec - s[1].length + 1).join('0');
            }
            
            return s.join(dec).replace(/\.[0]+$/, '');
        }
    };

    /**
     * Encapsulation
     * @return {Object} - this handle
     */
    root[common.className] = function () {

        function construct(constructor, args) {

            function Class() {
                return constructor.apply(this, args);
            }
            Class.prototype = constructor.prototype;
            return new Class();
        }

        var original = construct(Protected, arguments),
            Publicly = function () {};
        
        Publicly.prototype = {};
        [].forEach.call(common.publicMethods, function (member) {
            Publicly.prototype[member] = function () {
                return original[member].apply(original, arguments);
            };
        });

        return new Publicly(arguments);
    };

}(this));

window.Catalog = new Catalog();