///<reference path="/Web/Js/TESCO.js" />
///<reference path="/Web/Js/system/event.js" />
///<reference path="/Web/Js/system/event.manager.js" />
///<reference path="/Web/Js/system/exception.js" />
///<reference path="/Web/Js/system/DOM.node.js" />
///<reference path="/Web/Js/system/connection/XMLHTTP.js" />
///<reference path="/Web/Js/system/connection/ajax.js" />
///<reference path="/Web/Js/UI/position.js" />

TESCO.$("sites.retail.UI").Carousel = (function() {

	//	constants
    var NODE = TESCO.system.DOM.node;
    var EVENT = TESCO.system.event;
    var CONFIG = TESCO.sites.Configuration;

	//	public static
    EVENT.manager.call(_constructor.event = {}, "scroll");

	//	private static
    function _firstElement(arr) {
        if (arr) {
            if (arr[0]) return arr[0];
            if (arr.length == 0) return null;
            return arr;
        }
    }
    
    //	private instance
    //#region
    function _actuate(action) {
    
        //If we're on the last 'page'
        if (this.configuration.endItem - action > this.configuration.totalItems) {
            this.configuration.startItem = (this.configuration.totalItems - this.configuration.itemsInWindow)+1;
        } else {
            //If current startItem is a multiple of itemsInWindow then minus action, else find closest multiple
            if (this.configuration.startItem == 1 || (this.configuration.startItem-1) % CONFIG.carousel.step == 0) {
                this.configuration.startItem -= action;
            } else {
                this.configuration.startItem = this.configuration.startItem - (this.configuration.totalItems % this.configuration.itemsInWindow);
            }
        }
        this.configuration.endItem = this.configuration.startItem + (this.configuration.itemsInWindow);
       
        this.animateObj.scroll(this.configuration.itemWidth * (this.configuration.startItem - 1), 0, this.speed);
        _setButtonVisibility.call(this);
        if (CONFIG.carousel.paginationEnabled) {
            _updatePageData.call(this);
        }
          
        _tag.call(this);   
    }
    
    function _tag() {
        var _nextProds = _getCurrentCandidates.call(this);;
        var _prodObj = {}
        var _newProds = _nextProds.diff(this.configuration.currentCandidates);
        _prodObj.fsID = this.form.id.split("-")[1];
        _prodObj.products = _newProds;
        _constructor.event.dispatchEvent("scroll", _prodObj);   
        this.configuration.currentCandidates = _nextProds;
    }

    function _resizeContainer() {
        var _pxWidth = Math.floor((this.container.offsetWidth) / this.configuration.itemWidth) * this.configuration.itemWidth;
        this.configuration.itemsInWindow = Math.floor((this.container.offsetWidth) / this.configuration.itemWidth);
        this.configuration.endItem = this.configuration.startItem + this.configuration.itemsInWindow;
        _setButtonVisibility.call(this);
    }

	function _setButtonVisibility() {
        this.configuration.startItem == 1 ? 
			NODE.addClassName(this.previous, "pOff") : NODE.removeClassName(this.previous, "pOff");
        this.configuration.endItem > this.configuration.totalItems ? 
			NODE.addClassName(this.next, "nOff") : NODE.removeClassName(this.next, "nOff");
    }
    
    function _updatePageData() {
        //First reset all to 'off'
        var _pages = NODE.getElementsByClassName(this.container, "page");
        if (_pages) {
            for (var i = 0; i < _pages.length; i++) {
                NODE.removeClassName(_pages[i], "on");
                NODE.addClassName(_pages[i], "off");
            }
            
            //Work out which page is now active
            var _activePage = Math.ceil((this.configuration.startItem + this.configuration.itemsInWindow -1) / this.configuration.itemsInWindow);
            NODE.addClassName(_pages[_activePage - 1], "on");
            NODE.removeClassName(_pages[_activePage - 1], "off");
        }
    }

	//	attach events and handlers
    function _attachEventHandlers() {
        var _carousel = this;
        EVENT.attach(this.container, "click",
			function(e) {
			    var _control = e.target;
			    if (!_control.action) {
			        _control = _control.parentNode;
			    }
			    if (_control.action != undefined && 
					!NODE.hasClassName(_control, "pOff") && 
					!NODE.hasClassName(_control, "nOff")) {
			        _actuate.call(_carousel, _control.action);
			        e.prevent();
			    } else if (NODE.hasClassName(e.target, "page")) {
			        _paginate.call(_carousel, e);
			        e.prevent();
			    }
			}
		);

        EVENT.attach(window, "resize", 
			function() {
				_resizeContainer.call(_carousel);
			}
		);
    }
    
    function _getCurrentCandidates() {
        var _prods = NODE.getElementsByClassName(this.list, "cp");
        var _cProds = Array();
        for (var i = 0;i < this.configuration.totalItems; i++) {
            if (i < (this.configuration.startItem + this.configuration.itemsInWindow - 1) && i >= this.configuration.startItem - 1) {
                _cProds.push(_prods[i]);
            }
        }
        return _cProds;
    }
    
    function _configure() {
        this.configuration.totalItems = NODE.getElementsByClassName(this.list, "cp").length;
        this.configuration.windowWidth = this.list.parentNode.offsetWidth;
        this.configuration.itemWidth = parseInt(this.list.getElementsByTagName("li")[0].offsetWidth);
        this.configuration.startItem = 1;
        this.configuration.endItem = this.configuration.itemsInWindow = Math.floor((this.container.offsetWidth - 30) / this.configuration.itemWidth);
        this.list.style.width = (this.configuration.totalItems + 1) * this.configuration.itemWidth + TESCO.system.browser.px; // add one for rounding safety
        this.configuration.currentCandidates = _getCurrentCandidates.call(this);;
    }
    
    function _paginate(e) { 
        var _pageNum = e.target.className.trimLeft().split(" ")[0].split("-")[1];
        
        //If this is the last page, work out the final 5
        if (NODE.hasClassName(e.target, "last")) {
            this.configuration.startItem = (this.configuration.totalItems - this.configuration.itemsInWindow)+1;
        } else {
            this.configuration.startItem = (_pageNum * this.configuration.itemsInWindow)-(this.configuration.itemsInWindow-1);
        }

        this.configuration.endItem = this.configuration.startItem + this.configuration.itemsInWindow;

        this.animateObj.scroll(this.configuration.itemWidth * (this.configuration.startItem-1), 0, this.speed);
        _setButtonVisibility.call(this);
        _updatePageData.call(this);
        
        _tag.call(this);
    }
    
    function _configurePagination() {
        if (this.configuration.totalItems > this.configuration.itemsInWindow) {
            var _paginationContainer = document.createElement("div");
            NODE.addClassName(_paginationContainer, "paginationContainer");        
            this.configuration.numPages = Math.ceil(this.configuration.totalItems/this.configuration.itemsInWindow);
            
            var _firstMargin = (640 - (this.configuration.numPages * 25)) / 2;
            
            for (var i = 0; i < this.configuration.numPages; i++) {
                var _page = document.createElement("a");
                
                //Create classname
                var _classVal = "p-" + (i + 1);                
                _classVal += ((i == 0) ? TESCO.locale.carousel.on : TESCO.locale.carousel.off);
                if (i == this.configuration.numPages-1) _classVal+= " last";
                NODE.addClassName(_page, _classVal);
                //Add margin if this is the first page
                if (i == 0) {
                    _page.style.marginLeft = (_firstMargin + TESCO.system.browser.px);
                }
                //Add other attributes
                _page.setAttribute("href", document.location.href + "#");
                _page.setAttribute("title", TESCO.locale.carousel.title + (i + 1));
                
                _textSpan = document.createElement("span");
                NODE.addClassName(_textSpan, "hide");
                _textSpan.appendChild(document.createTextNode(TESCO.locale.carousel.title));
                _page.appendChild(_textSpan);
                _page.appendChild(document.createTextNode(i + 1));
                _paginationContainer.appendChild(_page);
            }
            
            //Create page counter
            this.container.appendChild(_paginationContainer);
        }
    }

	//	constructor
    function _constructor(speed, container, orientation) {
        this.container = document.getElementById(container);
        this.speed = speed;
        this.orientation = orientation;
        this.configuration = {};

        // create animation object
        this.previous = _firstElement(NODE.getElementsByClassName(this.container, "carousel-previous"));
		this.next = _firstElement(NODE.getElementsByClassName(this.container, "carousel-next"));
		this.form = _firstElement(NODE.getElementsByClassName(this.container, "featuredSpaceContainer"));
		this.list = _firstElement(this.form.getElementsByTagName("ul"));
		
        this.previous.action = CONFIG.carousel.step ;  // mark the buttons
        this.next.action = -(CONFIG.carousel.step);
        this.animateObj = new TESCO.UI.Rectangle.Position.Animation(this.form, false);
        _configure.call(this);
        this.animateObj.scrollTo(0, 0);  // reset the axis
        if (CONFIG.carousel.paginationEnabled) {
            _configurePagination.call(this);
        }
        _resizeContainer.call(this);
        _attachEventHandlers.call(this);
        return this;
    }
    _constructor.prototype.NAME = "TESCO.sites.retail.UI.Carousel";
    
    return _constructor;
})();

