$(function() {

    if (window.cart) { return false; }
    
    window.cart = function() {
    
        var
                _oREMOVE = 'REMOVE'
            ,   _oADD = 'ADD'
            ,   _oLOAD = 'LOAD'
            ,   _oOPT = 'OPT'
            ,   _oUPDATE = 'UPDATE'
            ,   _oCLEAR = 'CLEAR'
            ,   _oSEND = 'SEND'
            ,   _sOK = 'OK'

            ,   _MODE_LIST = 'burocratos_cart_mode_list'
            ,   _MODE_GALLERY = 'burocratos_cart_mode_gallery'
            ,   _MODE_KEY = 'burocratos_cart_mode'

            ,   _INVALID_ITEM_CLASSNAME             = 'cart-item-invalid-amount'

            ,   _MESSAGE_ORDER_HAS_INVALID_ITEMS    = 'Обратите внимание, что вы заказали больше товаров, чем у нас есть на складе. После подтверждения заказа недостающее количество товаров будет оформлено отдельным заказом.'

            ,   _LOCK_TIMEOUT = 60000;

            ;

        var
                _opt            = 1
            ,   _mode           = getCookie(_MODE_KEY).length ? getCookie(_MODE_KEY) : _MODE_LIST
            ,   _queue          = []
            ,   _items          = []
            ,   _INN            = ''
            ,   _phone          = ''
            ,   _contact        = ''
            ,   _lockTimeout    = null
            ;
            
        var

                _count = function() {
                    return _items.length;
                }

            ,   _$cartContainer = function() {
                    return $('#cart-container');
                } // end of _container

                // header of the shopping cart
            ,   _header = function(html) {
                    if ('undefined' == typeof html) {
                        if (!_$cartContainer().find('h2').size()) {
                            _$cartContainer().append('<h2></h2>');
                        }
                        return _$cartContainer().find('h2');
                    } else {
                        _header().html(html);
                    }
                } // end of _header

                // form of the shopping cart
            ,   _form = function(html) {
                    if ('undefined' == typeof html) {
                        if (!_$cartContainer().find('form#confform').size()) {
                            _$cartContainer().append('<form id="confform"></form>');
                        }
                        return _$cartContainer().find('form#confform');
                    } else {
                        _form().html(html);
                    }
                } // end of _header

                // get cart jQuery-items
            ,   _$cartItems = function() {
                    return  _$cartContainer().find('.basket-list tbody tr').size()
                                ? _$cartContainer().find('.basket-list tbody tr')
                                : _$cartContainer().find('.basket-gallery li.item')
                                ;
                } // end of _$cartItems

                // get cart item as jQuery-object
            ,   _$cartItem = function(itemDOMElement) {
                    return $(itemDOMElement);
                } // end of _$cartItem

                // get major DOM elements of cart item as jQuery-objects
            ,   _$cartItemElements = function(itemDOMElement) {
                    return {
                            '$delete'       : _$cartItem(itemDOMElement).find('a.cart-remove')
                        ,   '$photo'        : _$cartItem(itemDOMElement).find('.product-photo a')
                        ,   '$price'        : _$cartItem(itemDOMElement).find('span.product-price-value')
                        ,   '$amount'       : _$cartItem(itemDOMElement).find('.product-amount [type=text]')
                        ,   '$cost'         : _$cartItem(itemDOMElement).find('span.product-cost-value')
                        ,   '$addIcon'      : _$cartItem(itemDOMElement).find('.basket-amount-add')
                        ,   '$subtractIcon' : _$cartItem(itemDOMElement).find('.basket-amount-subtract')
                    };
                } // end of _$cartItemElements

                // returns jQuery-objects for such cart elements
                // as total-value, amount-value etc.
            ,   _$cartElements = function() {
                    return {
                            '$totalCost'        : _$cartContainer().find('#cart-total-cost .cart-total-cost-value')
                        ,   '$totalAmount'      : _$cartContainer().find('#cart-total-amount .cart-total-amount-value')
                        ,   '$confirmBtn'       : $('#cart-confirm')
                        ,   '$clearBtn'         : $('#cart-clear')
                        ,   '$invalidMessage'   : $('#invalid-items-amount-message')
                        ,   '$ajaxLock'         : $('#ajaxLock')
                    }
                } // end of _$cartElements

            ,   _$cartConfirmationAddPopup = function() {
                    // todo: not remove, not send, not clear
                    return $('#creo-confirmation');
                }

            ,   _$cartConfirmationAddPopupElements = function() {
                    return {
                            '$amount'       : _$cartConfirmationAddPopup().find('.basket-item-amount [type=text]')
                        ,   '$totalCost'    : _$cartConfirmationAddPopup().find('.total-price span')
                        ,   '$addIcon'      : _$cartConfirmationAddPopup().find('.basket-amount-add')
                        ,   '$subtractIcon' : _$cartConfirmationAddPopup().find('.basket-amount-subtract')
                    };
                }

            ,   _getINN = function() {
                    return _INN;
                }

            ,   _getContactName = function() {
                    return _contact;
                }

            ,   _getPhone = function() {
                    return _phone;
                }

            ,   _queueAjaxRequest = function(params) {
                    if (params) { 
                        _queue.push({
                                'operation': params.operation
                            ,   'params': params
                        }); 
                    }
                    if (1 == _queue.length) {
                        var operation = _queue[0].operation; params = _queue[0].params;
                        if (_needLockInterface(operation)) {
                            _lockInterface(operation);
                        }
                        switch(operation) {
                            case _oREMOVE: _removeItem(params); break;
                            case _oADD: _addItem(params); break;
                            case _oLOAD: _loadOrder(params); break;
                            case _oOPT: _makeOrderAsOpt(params); break;
                            case _oUPDATE: _updateItemAmount(params); break;
                            case _oCLEAR: _clearOrder(params); break;
                            case _oSEND: _sendOrder(params); break;
                        }
                    }
                }

            ,   _needLockInterface = function(operation) {
                    return  _oADD == operation
                        || _oREMOVE == operation
                        ||  _oSEND == operation
                        || _oCLEAR == operation
                        ;
                } // end of _needLockInterfaces

            ,   _lockInterface = function() {
                    _$cartElements().$ajaxLock.show();
                    _lockTimeout = setInterval(function() {
                        _dispatchAjaxResponse({
                                'operation' : operation
                            ,   'status'    : 'FAILED'
                            ,   'message'   : 'Операция прервана из-за слишком долгого времени выполнения.'
                            ,   'items'     : _items
                        });
                    }, _LOCK_TIMEOUT);
                }

            ,   _unlockInterface = function() {
                    if (_lockTimeout) {
                        clearTimeout(_lockTimeout);
                        _lockTimeout = null;
                    }
                    _$cartElements().$ajaxLock.hide();
                }

            ,   _removeItem = function(params) {
                    _updateInterface(true);
                    $.getJSON(
                            './?scenario=cart.remove'
                        ,   { 'id': params.id  }
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _addItem = function(params) {
                    _updateInterface(true);
                    $.getJSON(
                            './?scenario=cart.add'
                        ,   { 
                                    'id': params.id  
                                ,   'amount': params.amount
                            }
                        ,   _dispatchAjaxResponse
                    );
                }

            ,   _makeOrderAsOpt = function(checked) {
                    _updateInterface(true);
                    $.getJSON(
                            './php/ajax/cart.opt.php'
                        ,   { 'opt': checked }
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _loadOrder = function() {
                    _updateInterface(true);
                    $.getJSON(
                            './?scenario=cart.load'
                        ,   {  }
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _clearOrder = function() {
                    _updateInterface(true);
                    $.getJSON(
                            './?scenario=cart.clear'
                        ,   {  }
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _sendOrder = function() {
                    _updateInterface(true);
                    var params = {  
                            'captcha': $('#confcaptcha').val()
                        ,   'inn': $('#confinn').val()
                        ,   'contact': $('#confcontact').val()
                        ,   'phone': $('#confphone').val()
                        ,   'comment': $("#confcomment").val()
                    };
                    $.getJSON(
                            './?scenario=cart.send'
                        ,   params
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _updateItemAmount = function(params) {
                    _updateInterface(true);
                    $.getJSON(
                            './?scenario=cart.update'
                        ,   { 
                                    'id': params.id 
                                ,   amount: params.amount
                            }
                        ,   _dispatchAjaxResponse
                    );
                }
                
            ,   _dispatchAjaxResponse = function(response) {
                    _unlockInterface();
                    if (!response || !response.operation) {
                        error();
                    } else if (_oREMOVE == response.operation) {
                        _handleRemove(response);
                    } else if (_oADD == response.operation) {
                        _handleAdd(response);
                    } else if (_oLOAD == response.operation) {
                        _handleLoad(response);
                    } else if (_oOPT == response.operation) {
                        _handleOptChangeState(response);
                    } else if (_oUPDATE == response.operation) {
                        _handleUpdate(response);
                    } else if (_oCLEAR == response.operation) {
                        _handleClear(response);
                    } else if (_oSEND == response.operation) {
                        _handleSend(response);
                    }
                    _queue.splice(0, 1); _queueAjaxRequest();
                }
                
            ,   _isDisabled = function($element) {
                    return $element.hasClass('disabled');
                }
                
            ,   _disable = function($element, disable) {
                    disable
                        ? $element.addClass('disabled')
                        : $element.removeClass('disabled')
                        ;
                }
                
            ,   _updateInterface = function(ajax) {
                    ajax = !!ajax;
                    _disable(_$cartElements().$confirmBtn, ajax || _count() == 0);
                    _disable(_$cartElements().$clearBtn, ajax || _count() == 0);
                }
            
            ,   _showMessage = function(message) {

                    if ($('#cart-help').size()) { cart.help(); }

                    globalMessage(message);

                }
                
            ,   _handleAdd = function(response) {
                    if (_sOK == response.status) {
                        _showMessage('Товар успешно добавлен в корзину');
                        _markAsAdded(response.items);
                    } else {
                        _showMessage('Не удалось добавить товар в корзину.');
                    }

                    _handleLoad(response);
                }
                
            ,   _handleRemove = function(response) {
                    if (_sOK == response.status) {
                        _showMessage('Товар успешно удален из корзины');
                        _unmarkAsAdded([ { 'id' : response.id } ]);
                    } else {
                        _showMessage('Не удалось удалить товар из корзины.');
                    }

                    _handleLoad(response);
                }
                
            ,   _handleUpdate = function(response) {
                    if (_sOK == response.status) {
                        _showMessage('Изменение количества товара проведено успешно.');
                    } else {
                        _showMessage('Не удалось изменить количество товара в корзине.');
                    }

                    _handleLoad(response);
                }

            ,   _handleClear = function(response) {
                    if (_sOK == response.status) {
                        _showMessage('Ваша корзина успешно очищена');
                        _unmarkAsAdded(_items);
                    } else {
                        _showMessage('Не удалось очистить корзину');
                    }

                    _handleLoad(response);
                }

				// finds item by corresponding $cartItem
			,	_getItem = function($cartItem) {
					return _getItemById(
						parseInt($cartItem.attr('id').substr(9))
					);
				} // end of _getItem
				
				// get the index of item in the array
			,	_getItemIndexById = function(id) {
					var index = null;
					for (var i=0; i<_items.length; i++) {
						if (id == _items[i].id) {
							index = i;
						}
					} 
					return index;
				} // end of _getItemIndexById
				
			,	_getItemById = function(id) {
					return _items[_getItemIndexById(id)];
				}

			,	_removeItemFromCollection = function(id) {
					_items.splice(
							_getItemIndexById(id)
						,	1
					);
				}

            ,   _swap = function($fadeIn, $fadeOut) {
                    $fadeIn
                        .css({ 'opacity': 0, 'zIndex': 2 })
                        .animate({ 'opacity': 1 }, 200);
                    $fadeOut
                        .css({ 'opacity': 1, 'zIndex': 1 })
                        .animate({ 'opacity': 0 }, 200);
                } // end of swap

            ,   _markAsAdded = function(items) {
                    for (var index in items) {
                        _swap(
                                $('.rem' + items[index].id + '.cart-remove')
                            ,   $('.add' + items[index].id + '.cart-add')
                        );
                    }
                 } // end of _markAsAdded
                
            ,   _unmarkAsAdded = function(items) {
                    for (var index in items) {
                        _swap(
                                $('.add' + items[index].id + '.cart-add')
                            ,   $('.rem' + items[index].id + '.cart-remove')
                        );
                    }
                 } // end of _unmarkAsAdded

            ,   _validateGoodAmount = function(e, namespace, minValue) {
                    var
                            before  = namespace.control.get_value()
                        ,   after   = isNaN(parseInt(before)) ? minValue : parseInt(before)
                        ;

                    after = after < minValue ? minValue : after;
                    after = 0 == after % minValue ? after : Math.floor(after / minValue) * minValue;
                    $(namespace.html).val(after);
                    if (before != after) {
                        $(namespace.html).css('backgroundColor', 'red');
                        window.setTimeout(function() {
                            $(namespace.html).css("backgroundColor", "white");
                        }, 50);
                    }

                    return before == after;
                }
                
            ,   _handleSend = function(response) {
                    _showMessage(response.message);

                    if (_sOK == response.status) {
                        _unmarkAsAdded(_items);
                        if ($("#userUsersManagement").length > 0 || $("#userAccountManagement").length > 0 ) {
                           window.location.href = '/?scenario=cart.admin';
                        } else if (_isUserRegistered()) {
                            window.location.href = '/?scenario=my.orders';
                        } else {
                            window.location.href = '/';
                        }

                    }

                    _handleLoad(response);
                }

            ,   _buildSwitch = function() {
                    _$cartContainer().append(
                            '<div class="view-switcher">'
                        +       '<ul>'
                        +           '<li><a class="switcher-list ' + (_mode == _MODE_LIST ? 'current' : '') + ' " href="javascript:window.cart.switchToList();" title="Корзина списком"><span><ins></ins></span>списком</a></li>'
                        +           '<li><a class="switcher-gallery ' + (_mode == _MODE_GALLERY ? 'current' : '') + ' " href="javascript:window.cart.switchToGallery();" title="Корзина галереей"><span><ins></ins></span>галереей</a></li>'
                        +       '</ul>'
                        +   '</div>'
                    );
                }

            ,   _build = function(items) {
                    _buildSwitch();

                    _buildItemsHTML(items);

                    _buildTotals();

                    _buildUserData();
                }

            ,   _attachCartEvents = function() {
                    KIR.controls.parse(_$cartContainer());

                    _$cartItems().each(function() {

                        var self = this;

                        _$cartItemElements(this).$delete.click(function() {
                            // todo: not id but _$cartItemId
                            _self.remove(_getItem(_$cartItem(self)).id);
                        });

                        _$cartItemElements(this).$photo.lightbox();

                        var
                                previousAmount  = _$cartItemElements().$amount.val()

                            ,   updateTimeout

                            ,   _getLocalAmountChangeHandler = function(namespace, changeAmount) {

                                    return function(e) {

                                        _getAmountChangeHandler(
                                                _getItem(_$cartItem(self))
                                            ,   _$cartItemElements(self).$amount
                                            ,   _$cartItemElements(self).$cost
                                            ,   changeAmount
                                        )();

                                        if (previousAmount && previousAmount != namespace.control.get_value()) {

                                            if (updateTimeout) { clearTimeout(updateTimeout); }

                                            updateTimeout = window.setTimeout(
                                                    function() {
                                                        _queueAjaxRequest({
                                                                'id'        : namespace.html.id.substr(4)
                                                            ,   'amount'    : namespace.control.get_value()
                                                            ,   'operation' : _oUPDATE
                                                        });
                                                    }
                                                ,   500
                                            ); // updateTimeout

                                        } // previousAmount != namespace.control.get_value()

                                        previousAmount = namespace.control.get_value();

                                    }; // function(e)

                                } // _getLocalChangeAmountHandler

                            ;

                        _$cartItemElements(this).$addIcon.click(
                            _getLocalAmountChangeHandler(
                                    KIR(_$cartItemElements(this).$amount)
                                ,   1
                            )
                        );

                        _$cartItemElements(this).$subtractIcon.click(
                            _getLocalAmountChangeHandler(
                                    KIR(_$cartItemElements(this).$amount)
                                ,   -1
                            )
                        );

                        KIR.events(_$cartItemElements(this).$amount).change(
                            _getLocalAmountChangeHandler(
                                    KIR(_$cartItemElements(this).$amount)
                                ,   undefined
                            )
                        ); // change

                    }); // items.each

                    // todo: regexp
                    KIR.validator('confinn').required('Поле &laquo;ИНН&raquo; обязательно для ввода').change();
                    KIR.validator('confcontact').required('Поле &laquo;контактное лицо&raquo; обязательно для ввода').change();
                    KIR.validator('confphone').required('Поле &laquo;телефон&raquo; обязательно для ввода').change();
                    KIR.validator('confcaptcha').required('Поле &laquo;код на картинке&raquo; обязательно для ввода').change();
                    KIR.validator('confform').place('confmessages');
                }

            ,   _buildItemsHTML = function(items) {
                    _$cartContainer().append(
                        _mode == _MODE_LIST ? _buildListHTML(items) : _buildGalleryHTML(items)
                    );
                }

            ,   _buildTotals = function() {
                    _form().append(
                            '<div id="cart-total-cost">'
                        +       'Общая сумма заказа:&nbsp;<span class="cart-total-cost-value"></span>&nbsp;руб.'
                        +   '</div>'
                        +   '<div id="cart-total-amount">'
                        +       'Товаров в корзине:&nbsp;<span class="cart-total-amount-value"></span>'
                        +   '</div>'
                    );
                }

            ,   _buildUserData = function() {
                    var html = '';
                        html += '<div id="cart-user-data" class="form">';
                        html += '   <div class="form-title">';
                        html += '       <h2>Оформить заказ</h2>';
                        html += '   </div>';
                        html += '   <div id="invalid-items-amount-message"></div>'
                        html += '   <div id="confmessages"></div>';
                        html += '   <div class="field-grouping">';
                        html += '       <div class="field" id="field-confinn" style="float: left; margin-right: 20px; width: 116px;">';
                        html += '           <label for="confinn">ИНН:</label>';
                        html += '           <div class="field-inner">';
                        html += '               <input class="itext" type="text" id="confinn" name="inn" size="12" value="' + _getINN() + '" />';
                        html += '           </div>';
                        html += '       </div>';
                        html += '       <div class="field" id="field-conphone" style="float: left; margin-right: 20px; width: 142px;">';
                        html += '           <label for="confphone">Телефон:</label>';
                        html += '           <div class="field-inner">';
                        html += '               <input class="itext" type="text" id="confphone" name="phone" size="16" value="' + _getPhone() + '" />';
                        html += '           </div>';
                        html += '       </div>';
                        html += '       <div class="field" id="field-confcontact" style="float: left; width: 246px;">';
                        html += '           <label for="confcontact">Контактное лицо:</label>';
                        html += '           <div class="field-inner">';
                        html += '               <input class="itext" type="text" id="confcontact" name="contact" size="30" value="' + _getContactName() + '" />';
                        html += '           </div>';
                        html += '       </div>';
                        html += '   </div>'
                        html += '   <div id="field-confсomment" style="width: 544px;">';
                        html += '       <label for="confcomment">Коментарий:</label>';
                        html += '       <div class="field-inner">';
                        html += '           <textarea class="itextarea" id="confcomment" name="comment" rows="5" cols="80"></textarea>';
                        html += '           </div>';
                        html += '   </div>';
                        html += '   <div class="field field-captcha" style="clear: both; float: none;">';
                        html += '       <label for="confcaptcha">Код на картинке (5 символов):</label>';
                        html += '       <div class="field-inner">';
                        html += '           <img src="./php/mod/captcha.php" />';
                        html += '           <input class="itext icaptcha" type="text" id="confcaptcha" name="captcha" value="" />';
                        html += '       </div>';
                        html += '   </div>';
                        html += '   <div class="field button-controls">';
                        html += '       <ul class="buttons">';
                        html += '           <li>';
                        html += '               <a id="cart-confirm" class="button medium" href="javascript:void(0);" onclick="window.cart.confirm();"><span>Подтвердить</span></a>';
                        html += '           </li>';
                        html += '           <li>';
                        html += '               <a id="cart-clear" class="button medium" href="javascript:void(0);" onclick="window.cart.clear();"><span>Очистить</span></a>';
                        html += '           </li>';
                        html += '       </ul>';
                        html += '   </div>';
                        html += '</div>'

                    _form().append(html);
                }

                // todo: John Resig's template
            ,   _buildListHTML = function(items) {
                    var html =  '<table cellspacing="0" cellpadding="0" class="basket-list">'
                        +           '<col width="195" />'
                        +           '<col width="49" />'
                        +           '<col width="75" />'
                        +           '<col width="96" />'
                        +           '<col width="75" />'
                        +           '<col width="54" />'
						+ 			'<thead>'
						+				'<tr>'
						+					'<th class="product-title left" colspan="2">Наименование</th>'
						+					'<th class="product-price">Цена (руб.)</th>'
						+					'<th class="product-amount">Кол-во</th>'
						+					'<th class="product-cost right" colspan="2">Стоимость (руб.)</th>'
						+				'</tr>'
						+			'</thead>'
                        +           '<tbody>'
                        ;

                    // todo: even/odd
                    for (var i=0;i<items.length;i++) {
                        html +=         '<tr id="container' + items[i].id + '" class="' + (1==i%2 ? 'even' : 'odd')
                             +              ((items[i].left && items[i].left < items[i].amount) ? ' not-enough' : '') + '">'
                             +              '<td class="product-title left">'
                             +                  '<a href="?page=catalog&amp;scenario=catalog.goods.show&amp;goodsid=' + items[i].id +  '" class="'
                             +                      ((items[i].left && items[i].left < items[i].amount) ? 'not-enough' : '')
                             +                      '" data="' + parseInt(items[i].left) + ':' + parseInt(items[i].amount) + '">'
                             +                      items[i].name
                             +                  '</a>'
                             + 					'<br />'
                             +					'<span>Код/Арт.: <strong>' + items[i].code + '</strong> / <strong>' + items[i].art + '</strong></span>'
                             +          	'</td>'
                             +          	'<td class="product-photo">'
                             +              	'<a title="Фото" class="g_button photo lightbox-enabled" rel="lightbox" href="' + items[i].picture + '">'
                             +                  	'<span><ins></ins></span>'
                             +              	'</a>'
                             +          	'</td>'
                             +          	'<td class="product-price">'
                             +              	'<span class="product-price-value">' + items[i].price + '</span>'
                             +          	'</td>'
                             +          	'<td class="product-amount">'
                             +                   '<span class="basket-amount-subtract">&nbsp;&minus;&nbsp;</span>'
                             +                   '<input type="text" size="2" id="item' + items[i].id + '" name="item' + items[i].id + '" value="' + items[i].amount + '" />'
                             +                   '<span class="basket-amount-add">&nbsp;+&nbsp;</span>'
                             +          	'</td>'
                             +          	'<td class="product-cost">'
                             +              	'<span class="product-cost-value">' + burocratos.currency(_totalSum(items[i].price, items[i].amount)) + '&nbsp;руб.</span>'
                             +          	'</td>'
                             +          	'<td class="product-delete right">'
                             +              	'<a class="g_button cart cart-remove rem' + items[i].id + '" href="javascript:void(0);">'
                             +                  	'<span><ins></ins></span>'
                             +              	'</a>'
                             +          	'</td>'
                             +      	'</tr>';
                    }

                    html    +=      '</tbody>'
                            +   '</table>'
                            ;

                    return html;
                }
        
            ,   _buildGalleryHTML = function(items) {
                    var html = '<ul class="basket-gallery">'
                        ;
                    for (var i=0; i<items.length; i++) {
                        html += '<li id="container' + items[i].id + '" class="item' + ((items[i].left && items[i].left < items[i].amount) ? ' not-enough' : '') + '">'
                            +       '<h3>'
                            +           '<a href="?page=catalog&amp;scenario=catalog.goods.show&amp;goodsid=' + items[i].id + '" class="product_title'
                            +               ((items[i].left && items[i].left < items[i].amount) ? ' not-enough' : '')
                            +               '" data="' + parseInt(items[i].left) + ':' + parseInt(items[i].amount) + '">'
                            +               items[i].name
                            +           '</a>'
                            +       '</h3>'
							+		'<p><span>Код/Арт.: <strong>' + items[i].code + '</strong> / <strong>' + items[i].art + '</strong></span></p>'
                            +       '<div class="product-photo">'
                            +           '<a title="Фото" class="g_button photo lightbox-enabled" rel="lightbox" href="' + items[i].picture + '">'
                            +               '<img title="' + items[i].name + '" alt="' + items[i].name + '" src="' + items[i].icon + '" />'
                            +           '</a>'
                            +       '</div>'
							+		'<div class="product_properties">'
                            +       	'<ul>'
							+				'<li>Цена: <span class="product-price-value">' + items[i].price + '</span>&nbsp;руб.</li>'
							+				'<li>Кол-во: <span class="product-amount">'
                            +                   '<span class="basket-amount-subtract">&nbsp;&minus;&nbsp;</span>'
                            +                   '<input type="text" id="item' + items[i].id + '" name="item' + items[i].id + '" value="' + items[i].amount + '" />'
                            +                   '<span class="basket-amount-add">&nbsp;+&nbsp;</span>'
                            +               '</span></li>'
							+				'<li>Сумма: <span class="product-cost-value">' + _totalSum(items[i].price, items[i].amount, items[i].rate) + '</span>&nbsp;руб.</li>'
                            +       	'</ul>'
							+		'</div>'
                            +       '<a class="rem' + items[i].id + ' g_button cart cart-remove" href="javascript:void(0);"><span><ins></ins></span></a>'
                            +   '</li>'
                            ;
                    }
                    html += '</ul>'
                        ;

                    return html;
                }

            ,   _buildConfirmAddHTML = function(orderInfo) {
                    return  '<p class="message">Добавить следующий товар в корзину?</p>'
                        +   '<ul class="basket-item">'
                        +       '<li class="basket-item_title">'
                        +           '<a href="./?page=catalog&amp;scenario=catalog.goods.show&amp;goodsid="' + orderInfo.id + '">'
                        +               orderInfo.name
                        +           '</a>'
                        +           '<br />'
                        +           '<span>Код: ' + orderInfo.code + '</span>'
                        +       '</li>'
                        +       '<li class="basket-item_price"><span>'
                        +           orderInfo.price + '&nbsp;руб.'
                        +       '</span></li>'
                        +       '<li class="basket-item-amount">'
                        +           '<span class="basket-amount-subtract">&nbsp;&minus;&nbsp;</span>'
                        +           '<input type="text" class="itext" name="amount" size="2" value="' + (orderInfo.amount ? orderInfo.amount : (orderInfo.apiece ? 1 : orderInfo.count)) + '" />'
                        +           '<span class="basket-amount-add">&nbsp;+&nbsp;</span>'
                        +       '</li>'
                        +   '</ul>'
                        +   '<p class="total-price">'
                        +       '=<span>' + burocratos.currency(_totalSum(orderInfo.price, orderInfo.apiece ? 1 : orderInfo.count, orderInfo.rate)) + '</span>&nbsp;руб.'
                        +   '</p>'
                        ;
                }

            ,   _buildWarningMessage = function(orderInfo) {
                    var
                            warningMessage = ''

                        ,   buildItem = function(info) {
                                return '<li>'
                                +           '<div class="item-title">'
                                +               '<span>' + info.name + '</span>'
                                +           '</div>'
                                +           '<div class="item-left"><span>' + info.left + '</span></div>'
                                +           '<div class="item-amount"><span>' + info.amount + '</span></div>'
                                +       '</li>';
                            }

                        ;

                    if($("a.not-enough").length || orderInfo)
                    {
                        warningMessage += '<p class="failing-quantity"><span style="color: #CB0303">Внимание!</span> Количество некоторых товаров, указанных в&nbsp;заказе, превышает количество на&nbsp;складе. Недостающее количество следующих товаров будет оформлено отдельным заказом.</p>'
                        warningMessage += '<ul class="failing-items">';
                        warningMessage += '<li>'
                            +           '<div class="item-title">'
                            +               '<span>Наименование</span>'
                            +           '</div>'
                            +           '<div class="item-left"><span>Остаток</span></div>'
                            +           '<div class="item-amount"><span>Заказанное кол-во</span></div>'
                            +       '</li>';
                        if (!orderInfo) {
                            $("a.not-enough").each(function(index, elem){
                                var data = $(elem).attr('data');
                                warningMessage += buildItem({
                                        'name'      : $(elem).text()
                                    ,   'left'      : data.split(':')[0]
                                    ,   'amount'    : data.split(':')[1]
                                });
                            });
                        } else {
                            warningMessage += buildItem(orderInfo);
                        }
                        warningMessage += '</ul>';
                    } else {
                        warningMessage += '<p class="message">Отправить заказ менеджеру?</p>'
                    }

                    return warningMessage;
                }

            ,   _getAmountChangeHandler = function(orderInfo, $amount, $totalCost, changeStep) {
                    return function(e) {
                        var minValue = orderInfo.apiece ? 1 : orderInfo.count;

                        if ('undefined' != typeof changeStep) {
                            $amount.val(
                                    parseInt($amount.val())
                                +   changeStep * minValue
                            );
                        } // undefined != changeAmount

                        if (_validateGoodAmount(e, KIR($amount), minValue)) {
                            $totalCost.html(
                                burocratos.currency(_totalSum(
                                        orderInfo.price
                                    ,   parseInt($amount.val())
                                    ,   orderInfo.rate
                                ))
                            );
                        } // validateGoodAmount
                    }; // return function
                 } // getChangeHandler

            ,   _attachConfirmAddEvents = function(orderInfo, $amount, $totalCost) {
                    KIR.events(_$cartConfirmationAddPopupElements().$amount).typing(_getAmountChangeHandler(orderInfo, $amount, $totalCost/* undefined */));
                    _$cartConfirmationAddPopupElements().$subtractIcon.click(_getAmountChangeHandler(orderInfo, $amount, $totalCost, -1));
                    _$cartConfirmationAddPopupElements().$addIcon.click(_getAmountChangeHandler(orderInfo, $amount, $totalCost, 1));
                }
                
            ,   _handleLoad = function(response) {
                    _items      = response.items;
                    _INN        = response.inn;
                    _contact    = response.contact;
                    _phone      = response.phone;
            
                    _$cartContainer().empty();
                    
                    if ($('#cart-help').size()) { cart.help(); }

                    _header('Ваша корзина <span class="hint"><a class="title-help" href="?page=conditions" target="_blank">что это?</a></span>');
                    
                    if (_count()) {
                        _build(_items);
                        _attachCartEvents();
                    }

                    if (response.message && response.message.length) { _showMessage(response.message); }

                    _calculateTotals();
                    _checkOrderForValidity();
                    _updateInterface();
                }

            ,   _handleOptChangeState = function(response) {
                    _opt = parseInt(response.opt);
                    if (_sOK == response.status) {
                        _showMessage('Статус заказа успешно изменен.');
                    } else {
                        _showMessage('Не удалось изменить статус заказа.');
                        $('[name=opt]').attr('checked', _opt ? 'checked' : '');
                    }
                    _calculateTotals();
                    _updateInterface();
                }

            ,   _calculateTotals = function() {
                    if (!_count()) { // todo: remove this if branch
                        _header('Ваша корзина пуста <span class="hint"><a class="title-help" href="?page=conditions" target="_blank">что это?</a></span>');
                        _$cartElements().$totalCost.html('0');
                        _$cartElements().$totalAmount.html('0');
                    } else {

                        var totalSum = 0;

                        _$cartItems().each(function() {
                            var itemCost = _totalSum(
                                    _getItem(_$cartItem(this)).price
                                ,   parseFloat(_$cartItemElements(this).$amount.val())
                                ,   _getItem(_$cartItem(this)).rate
                            );
                            _$cartItemElements(this).$cost.html(burocratos.currency(itemCost));
                            totalSum += itemCost;
                         });

                        _$cartElements().$totalCost.html(burocratos.currency(totalSum)); // todo: currency function
                        _$cartElements().$totalAmount.html(_$cartItems().size());

                    }
                }
                
            ,   error = function() {
                }

            ,   _totalSum = function(price, amount, rate) {
                    price = new Number(price);
                    amount = new Number(amount);
                    rate = new Number(rate);
                    price = price * 100 / (100 + rate);
                    price = new Number(price).toFixed(2);
                    price *= amount;
                    price = price * (100 + rate) / 100;
                    price = new Number(price).toFixed(2);
                    return new Number(price);
                }

            ,   _switch = function(mode) {
                    if (mode == _mode) { return; }

                    setCookie(_MODE_KEY, mode, 30);
                    _mode = mode;

                    cart.cart();
                }

            ,   _isItemInvalid = function(item) {
                    return  'undefined' != item.left
                        &&  item.left < item.amount
                        &&  _isUserRegistered()
                        ;
                } // end of _isItemInvalid

            ,   _isUserRegistered = function() {
                    return !$("#login-button").size();
                } // end of _isUserRegistered

            ,   _checkOrderForValidity = function() {
                    var invalid = false;

                    _$cartItems().each(function() {
                        if (_isItemInvalid(_getItem(_$cartItem(this)))) {
                            _$cartItem(this).addClass(_INVALID_ITEM_CLASSNAME);
                            invalid = true;
                        } else {
                            _$cartItem(this).removeClass(_INVALID_ITEM_CLASSNAME);
                        }
                    });

                    _$cartElements().$invalidMessage.html(
                        invalid ? _MESSAGE_ORDER_HAS_INVALID_ITEMS : ''
                    );
                } // end of _checkCartForValidity

            ;
        
        var _self = {
        
                add: function(orderInfo) {

                    var

                            checkUpAmount = function() {
                                var newOrderInfo = orderInfo;

                                newOrderInfo.amount = parseInt($('#creo-confirmation input[name=amount]').val());

                                if (_isItemInvalid(newOrderInfo)) {
                                    creoConfirm(
                                            'Корзина'
                                        ,   _buildWarningMessage(newOrderInfo)
                                        ,   getSubmitRequest(newOrderInfo)
                                        ,   {  }
                                        ,   function() {
                                                selectAmount(newOrderInfo);
                                            }
                                        ,   {
                                                    'confirm'   : 'Подтверить'
                                                ,   'cancel'    : 'Редактировать'
                                            }
                                    );
                                } else {
                                    getSubmitRequest(newOrderInfo)();
                                }
                            }

                        ,   getSubmitRequest = function(orderInfo) {
                                return function() {
                                    _queueAjaxRequest({
                                                'id'        : orderInfo.id
                                            ,   'operation' : _oADD
                                            ,   'amount'    : orderInfo.amount
                                    });
                                };
                            }

                        ,   selectAmount = function(orderInfo) {
                                creoConfirm(
                                        'Корзина'
                                    ,   _buildConfirmAddHTML(orderInfo)
                                    ,   checkUpAmount
                                    ,   {  }
                                );

                                KIR.controls.parse(_$cartConfirmationAddPopup());

                                _attachConfirmAddEvents(
                                        orderInfo
                                    ,   _$cartConfirmationAddPopupElements().$amount
                                    ,   _$cartConfirmationAddPopupElements().$totalCost
                                );
                            }

                        ;

                    selectAmount(orderInfo);
                }
            
            ,   remove: function(id) {
                    creoConfirm(
                            'Удаление товаров'
                        ,   '<p class="message">Вы уверены, что хотите удалить этот товар из корзины?</p>'
                        ,   _queueAjaxRequest
                        ,   { 
                                    'id': id
                                ,   'operation': _oREMOVE 
                            }    
                    );
                }
            
            ,   cart: function() {
                    _queueAjaxRequest({ 'operation': _oLOAD });
                } // end of cart
                
            ,   confirm: function() {
                    if (_isDisabled(_$cartElements().$confirmBtn)) { return false; }
                    if (!KIR.validator('confform').validate()) { return false; }

                    creoConfirm(
                            'Подтверждение заказа'
                        ,   _buildWarningMessage()
                        ,   _queueAjaxRequest
                        ,   { 'operation': _oSEND }
                    );
                }
                
            ,   clear: function() {
                    if (_isDisabled(_$cartElements().$clearBtn)) { return false; }
                    creoConfirm(
                            'Очистка корзины'
                        ,   'Вы уверены, что хотите очистить корзину?'
                        ,   _queueAjaxRequest
                        ,   { 'operation': _oCLEAR }    
                    );
                }
                
            ,   orders: function(e, row) {

                    var target = e.target ? e.target : e.srcElement;

                    if ($(target).is('.my-orders-print-link a')) { return true; }

                    var 
                            items = $(row).parents('table').find('.orderitems')
                        ,   count = 0
                        ,   handle = function() {
                                if (items.length) { $(this).css('display', 'none'); }
                                if (++count < items.length) { return false; }

                                items = $(row); if ('expanded' == items.data('state')) {
                                    items.data('state', 'collapsed');
                                } else {
                                    items.data('state', 'expanded');
                                    while (items.next().length && items.next().hasClass('orderitems')) {
                                        items = items.next();
                                        items.css('display', 'table-row').animate({ opacity:1 }, 200);
                                    }
                                }
                            };
                            
                    items.length
                        ? items.animate({ opacity:0 }, 200, handle)
                        : handle();
                }
                
            ,   help: function() {
                    if (!$('#cart-help').size()) {
                        _header()
                            .after('<div id="cart-help"></div>')
                            .find('a.title-help')
                                .html('скрыть')
                                .addClass('title-help-shown');
                        $('#cart-help')
                            .addClass('loading')
                            .load('./php/load/cart.faq.php', function() {
                                $('#cart-help')
                                    .removeClass('loading');
                            });
                    } else {
                        _header()
                            .find('a.title-help')
                                .html('что это?')
                                .removeClass('title-help-shown');
                        $('#cart-help').hide(200, function() {
                            $('#cart-help').remove();
                        });
                    }
                }

            ,   switchToList: function() {
                    _switch(_MODE_LIST);
                }

            ,   switchToGallery: function() {
                    _switch(_MODE_GALLERY);
                }

        };
        
        return _self;
        
    }();
    
});
