///<reference path="../../TESCO.js" />
///<reference path="../../event.js" />
///<reference path="../../eventManager.js" />
///<reference path="../../node.js" />
///<reference path="../entities.js" />
///<reference path="../basket.js" />
///<reference path="entities.js" />

TESCO.$("sites.UI").Basket = (function() {

    //  private static
    //#region
    //	id="{shelf/@type}-{basket/@type}"
    TESCO.UI.Basket.Shelf.types.add("Excluded-Active");

    var PRODUCT = TESCO.UI.entities.Product;
    var NODE = TESCO.system.DOM.node;
    var EVENT = TESCO.system.event;
    var SHELF = TESCO.UI.Basket.Shelf;
    var _excludedRows = [];
    var _warning;

    function _getExcludedRow(id) {
        var _row = null;
        for (var i = 0, L = _excludedRows.length; i < L; i++) {
            if (_excludedRows[i].id === id) {
                _row = _excludedRows[i];
                break;
            }
        }
        return _row;
    }

    EVENT.attach(PRODUCT.event, "quantityupdatestart", _quantityUpdateStart);
    EVENT.attach(PRODUCT.event, "quantityupdateend", _quantityUpdateEnd);
    EVENT.attach(PRODUCT.event, "quantityupdateerror", _quantityUpdateError);

    function _quantityUpdateStart(product) {
        if (product.action === PRODUCT.actions.include) {
            var _row = product.sourceBasket.getRowByProduct(product);
            _row.hide(); //	hide the row in the excluded shelf
            var _shelf = SHELF.getByType("Excluded-Active");
            if (_shelf.isEmpty(product.sourceBasket)) {
                _shelf.collapse();
            }
            var _i = _excludedRows.length;
            _excludedRows.push({
                "tr": _row.tr,
                "id": product.getId(),
                "i": _i,
                "shelf": _shelf
            });    //  store the excluded tr   

            //	the new row in the active shelf
            var _row = product.sourceBasket.createRow(null, product); //	optimistic
            _row.insert(SHELF.getByType(product.sourceBasket.defaultShelfType).tbody());
        }
    }

    function _quantityUpdateError(product) {
        if (product.action === PRODUCT.actions.include) {
            var _expand = false;
            var _row = _getExcludedRow(product.getId());
            if (_row.shelf.isEmpty(product.sourceBasket)) {
                _expand = true;
            }
            product.sourceBasket.createRow(_row.tr, product).show();    // show the old row
            if (_expand) {
                _row.shelf.expand();
            }
            _excludedRows.splice(_row.i, 1);
        }
    }

    function _quantityUpdateEnd(product) {
        if (product.action === PRODUCT.actions.include) {
			var _row = _getExcludedRow(product.getId());
			new TESCO.UI.Basket.Row(product.sourceBasket, _row.tr).remove();    //  delete the old tr in the excluded shelf
			_excludedRows.splice(_row.i, 1);
        }
    }

	function _deleteStrictTr(containerId) {
        //	delete tr for xhtml strict validation
        var _id = containerId.substr(containerId.lastIndexOf("-") + 1);
        var _extraRow = document.getElementById("tr-excluded-" + _id);
        if (_extraRow) {
			_extraRow.parentNode.removeChild(_extraRow);
        }
    }
    //#endregion

    //  private instance
    //#region
    function _createContainers() {
        _warning = document.getElementById("basket-warning-Active");
        this.tables = this.container.getElementsByTagName("table");
    }

    function _updateTableSummary() {
        for (var i = 0, L = this.tables.length; i < L; i++) {
            var _trs = this.tables[i].getElementsByTagName("tr");
            var _count = _trs.length - 1; // subtract a row for thead
            for (var ii = 0, LL = _trs.length; ii < LL; ii++) {
				if (_trs[ii].style.display === "none") {
					_count--;
				}
			}            
            var _summary = TESCO.locale.basket.tableSummary.format((this.view === TESCO.UI.Basket.views.midi ? "6" : "7"), _count, (_count === 1 ? "" : "s"));
            this.tables[i].setAttribute("summary", _summary);
        }
    }

    function _setCheckoutState(disable, node, attributes) {
        var _img = node.getElementsByTagName("img")[0];
        if (disable) {
            _img.src = TESCO.locale.basket.checkout[TESCO.UI.Basket.viewString(this.view)].disabled;
            _img.alt = "";
            if (this.view === TESCO.UI.Basket.views.midi) {
                //  set checkout warning dialogue status
                var _a = document.getElementById("CheckoutBasketLink");
                if (_a.warned) {
                    _a.setAttribute("href", TESCO.locale.basket.checkout.warningHref);
                } else {
                    NODE.addClassName(_img, "dialogue");
                }
            }
        } else {
            _img.src = TESCO.locale.basket.checkout[TESCO.UI.Basket.viewString(this.view)].enabled;
            _img.alt = TESCO.locale.basket.checkout.proceed;
            if (this.view === TESCO.UI.Basket.views.midi) {
                NODE.removeClassName(_img, "dialogue");
            }
        }
    }
    //#endregion

    //  constructor
    function _constructor(containerId, view) {
        //  set default shelf
        if (!this.defaultShelfType) {
            SHELF.Default.type.set(this, "Active-Active");
        }
        _deleteStrictTr(containerId);
        _constructor.base.constructor.apply(this, arguments);
        _createContainers.call(this);
        this.history = new TESCO.system.connection.ajax.History(containerId);        
		if (this.history.stale()) {
            PRODUCT.refresh(this, TESCO.UI.Basket.actions.refresh);
        }
        return this;
    }
    _constructor.extend(TESCO.UI.Basket);

    //	public instance
    //#region
    _constructor.prototype.NAME = "TESCO.sites.UI.Basket";

    _constructor.prototype.setCheckoutLinks = function(disable, attributes) { //  augment base
        _constructor.base.setCheckoutLinks.call(this, disable || attributes["canCheckOut"].nodeValue === "false", attributes, this.container, _setCheckoutState);
    }

	_constructor.prototype.deleteRow = function(tr) {
		var _row = this.getRowById(tr.id);
		var _shelfType = SHELF.getTypeFromTr(this, tr);
		_constructor.base.deleteRow.call(this, tr);
		if (_shelfType === "Excluded-Active") {
			var _shelf = SHELF.getByType(_shelfType);
			if (_shelf.isEmpty()) {
				_shelf.collapse();
			}
		}
	}

    _constructor.prototype.post = function(callback, url, entity, errorCallback) {  //  augment base
        this.history.record();
        _constructor.base.post.apply(this, arguments);
    }

    _constructor.prototype.getClickAction = function(target) {
        var _control = {}
        _control.action = NODE.getAction([{ "val": "moveToBasket", "className": "moveToBasket"}], target);
        if (_control.action == "moveToBasket") {
            var _productId = this.getProductId(this.getTr(target));
            _control.product = PRODUCT.getProductById(_productId);
        }
        return _control;
    }

    _constructor.prototype.clickHandler = function(e) {
        var _caught = _constructor.base.clickHandler.call(this, e);
        if (!_caught) {
            var _control = this.getClickAction(e.target);
            if (_control.action == "moveToBasket") {    // move from excluded shelf
                _control.product.updateBasketQuantity(PRODUCT.steps.move, this, { "name": "basket" }, this);
                e.prevent();
            }
        }
    }

    _constructor.prototype.render = function(html) { //	update warnings
        if (_warning) {
            if (_warning.hasChildNodes()) {
                NODE.removeChildNodes(_warning);
            }
            var _newMsgs = NODE.getElementsByClassAndTagName(html, "basketWarning", "div");
            if (_newMsgs) { //	count down to prevent errors caused by response being modified
                for (var i = _newMsgs.length - 1; i >= 0; i--) {
                    _warning.appendChild(_newMsgs[i]);
                }
            }
        }
        _constructor.base.render.call(this, html);
        _updateTableSummary.call(this);
    }
    //#endregion

    //  return constructor as pointer
    return _constructor;
})();

TESCO.$("sites.UI.Basket").Previous = (function() {

    //  private static
    //#region

    //	id="{shelf/@type}-{basket/@type}"
    TESCO.UI.Basket.Shelf.types.add("Excluded-PreviousBasket");

    var _activeBasket;
    var PRODUCT = TESCO.UI.entities.Product;
    var EVENT = TESCO.system.event;
    var _name = "TESCO.sites.UI.Basket.Saved";

    EVENT.attach(PRODUCT.event, "quantityupdatestart", _quantityUpdateStart);
    EVENT.attach(PRODUCT.event, "quantityupdateend", _quantityUpdateEnd);
    EVENT.attach(PRODUCT.event, "quantityupdateerror", _quantityUpdateError);

    function _quantityUpdateError(product) {
        if (product.action === PRODUCT.actions.move) {
            product.sourceBasket.getRowByProduct(product).show();
        }
    }

    function _quantityUpdateStart(product) {
        if (product.action === PRODUCT.actions.move) {
            product.sourceBasket.getRowByProduct(product).hide();
        }
    }

    function _quantityUpdateEnd(product) {
        var _basket;
        switch (product.action) {
			case PRODUCT.actions.move :
				_basket = product.sourceBasket;
				_basket.getRowByProduct(product).remove();
				break;
			case PRODUCT.actions.remove :
				if (product.basket.NAME === _name) {
					_basket = product.basket;
				}
				break;
        }
        if (_basket) {
            if (!PRODUCT.getProductsInBasket(_basket.id).length) {
                //  empty, delete
                _dispose.call(_basket);
            }
        }
    }
    //#endregion

    //  private instance
    //#region
    function _dispose() {
        var _basket = this;
        var _container = new TESCO.UI.Collapse(_basket.container, false);
        _container.addEventListener("complete",
			function() {
			    _container.removeEventListener("complete", arguments.callee);
			    EVENT.detach(PRODUCT.event, "quantityupdateerror", _quantityUpdateError);
			    EVENT.detach(PRODUCT.event, "quantityupdateend", _quantityUpdateEnd);
			    EVENT.detach(PRODUCT.event, "quantityupdatestart", _quantityUpdateStart);
			    delete _basket;
			}
		);
        _container.collapse();
    }
    //#endregion

    //  constructor
    function _constructor(containerId, view) {
        TESCO.UI.Basket.Shelf.Default.type.set(this, "Active-PreviousBasket");
        _constructor.base.constructor.apply(this, arguments);
        if (!_activeBasket)
            _activeBasket = TESCO.sites.Configuration.activeBasket;
        return this;
    }
    _constructor.extend(TESCO.sites.UI.Basket);

    //	public instance
    //#region
    _constructor.prototype.NAME = _name;

    _constructor.prototype.clickHandler = function(e) {	//	override TESCO.sites.UI.Basket clickHandler
        var _caught = _activeBasket.constructor.base.clickHandler.call(this, e);
        if (!_caught) {
            var _control = _constructor.base.getClickAction.call(this, e.target);
            if (_control.action == "moveToBasket") {
                _control.product.updateBasketQuantity(PRODUCT.steps.move, _activeBasket, { "name": "basket" }, this);
                e.prevent();
            }
        }
    }

    //#endregion

    //  return constructor as pointer
    return _constructor;
})();