﻿TESCO.UI.Flyout.Transient = (function() {

    //  private static
    var _listening = false;
    var _active = false;
    var _timer;
    var _registary = [];
    var CONFIG = TESCO.sites.Configuration;
    var FLYOUT = TESCO.UI.Flyout;
    var NODE = TESCO.system.DOM.node;

    function _removeListener(callee) {
        FLYOUT.opacity.removeEventListener("complete", callee);
        _listening = false;
    }

    function _completeFade(e) {
        _removeListener(_completeFade);
        _active = false;
        _constructor.base.hide.call(e);
    }

    //  private instance
    function _measureIntent(container, f, x, y) {
        clearTimeout(this.intentTimer);
        var _transient = this;
        if (_active) {
            f();
            return;
        }
        if (x && y) {
            if ((Math.abs(x - this.x) + Math.abs(y - this.y)) < 
                CONFIG.flyout.transient.hover.sensitivity) {
                f();
                return;
            }
        } 
        var _oldX = this.x;
        var _oldY = this.y;
        _transient.intentTimer = setTimeout(
            function() {
                _measureIntent.call(_transient, node, f, _oldX, _oldY);
            }, CONFIG.flyout.transient.hover.interval
        );
    }

    //	public static
    _constructor.stop = function() {
        _removeListener(_completeFade);
        _active = false;
        FLYOUT.opacity.stop();
    }
    
    TESCO.system.event.manager.call(_constructor.event = {}, "loaded");

    //  constructor
    //#region 
    function _constructor(container, x, y, className) {
        var _transient = this;
        TESCO.system.event.attach(container, "mouseover",
            //  TESCO.UI.hover.Intent(container,
            function(e) {
                if (NODE.hasClassName(e.target, className || "flyout")) {   //  elements with flyout class
                    var _id = e.target.id;
                    if (_id) {
                        e.stop();
                        _measureIntent.call(_transient, container, 
                            function() {
                                var _key = _id.slice(_id.indexOf("-") + 1, _id.length);
                                FLYOUT.mouseover = true;
                                if ((FLYOUT.state !== FLYOUT.states.none) && (_key === FLYOUT.key)) {
                                    _transient.dispatchEvent("over", {});   //  already showing or loading this flyout
                                } else {
                                    FLYOUT.key = _key;
                                    _transient.load({
                                        "target": e.target,
                                        "type": _id.slice(0, _id.indexOf("-"))
                                    }, FLYOUT.key);
                                }
                            }
                        );
                    } else {
                        throw new Error("TESCO.UI.Flyout.Transient: '" + e.target + "' id attribute is required");
                    }
                }
            }
        );
        
        TESCO.system.event.attach(container, "mouseout", 
			function(e) {
				if (!NODE.isAncestor(e.relatedTarget, container)) {
					clearTimeout(_transient.intentTimer);
				}
			}
		);

        this.addEventListener("over",
		    function() {
		        clearTimeout(_timer);
		        if (_active) {
		            if (FLYOUT.opacity.active() && FLYOUT.opacity.direction === TESCO.UI.effects.Opacity.directions.down) {	//  is it fading out?
		                _transient.fadeUp(true); //  fade back up quickly
		            }
		        }
		    }
	    );
	
        TESCO.system.event.attach(container, "mousemove", 
            function(e) {
                _transient.x = e.pageX;
                _transient.y = e.pageY;
            }
        );

        this.addEventListener("out",
		    function() {
				clearTimeout(_transient.intentTimer);
		        if (_active)
		            _transient.hide();
		    }
	    );
        this.position = {
            "x": x || FLYOUT.position.x.left,
            "y": y || FLYOUT.position.y.bottom
        }
        return this;
    }
    //#endregion
    TESCO.sites.UI.Flyout.extend(_constructor);

    //	public instance
    //#region
    //  public default
    _constructor.prototype.NAME = "TESCO.UI.Flyout.Transient";

    //  public methods
    _constructor.prototype.fadeUp = function(fast) {
        if (_listening) {
            _removeListener(_completeFade);
        }
        clearTimeout(_timer);
        _constructor.base.fadeUp.call(this, fast);
    }

    _constructor.prototype.fadeDown = function() {
        if (_listening) {
            _removeListener(_completeFade);
        }
        if (FLYOUT.state !== FLYOUT.states.none) {
            _constructor.base.fadeDown.call(this);
        }
    }

    _constructor.prototype.show = function(e, content, fast) {
        _active = true;
        clearTimeout(_timer);
        _constructor.base.show.apply(this, arguments);
    }

    _constructor.prototype.load = function() {
        _active = true;
        clearTimeout(_timer);
        _constructor.base.load.apply(this, arguments);
    }

    _constructor.prototype.loaded = function() {
        //	unused abstract implementation
    }

    //  augment base hide method
    _constructor.prototype.hide = function() {
        if (FLYOUT.state !== FLYOUT.states.none) {
            clearTimeout(_timer);
            var _transient = this;
            _timer = setTimeout(
				function() {
				    if (TESCO.system.browser.opacity) {
				        if (_listening) {
				            _removeListener(_completeFade);
				        }
				        FLYOUT.opacity.addEventListener("complete", _completeFade);
				        _transient.fadeDown();
				        _listening = true;
				    } else {
				        _active = false;
				        _constructor.base.hide.call(_transient);
				    }
				},
                //	begin hide transition quickly if it's loading
				(FLYOUT.state === FLYOUT.states.showing) ? TESCO.sites.Configuration.flyout.hideDelay : 1
			);
        }
    }
    //#endregion

    //  return constructor as function pointer
    return _constructor;
})();

TESCO.UI.Flyout.Navigation = (function() {

    //  private static
    var _path = TESCO.sites.Configuration.application.path + "/Ajax/GetNavigationGroup.aspx";

    var _urls = {
        "product": _path,
        "favourite": _path,
        "promotion": _path
    }

    //   constructor
    function _constructor(container, x, y) {
        //Loop though all tertNavContent ul's and cache each one
        var _navigationData = TESCO.system.DOM.node.getElementsByClassName(container, "tertNavContent");
        if (_navigationData) {
			for (var i = 0, L = _navigationData.length; i < L; i++) {
				var _id = _navigationData[i].id.slice(_navigationData[i].id.indexOf("-") + 1);
				TESCO.UI.Flyout.cache.setItem(_id, _navigationData[i]);
			}
			_constructor.base.constructor.call(this, container, x, y);
			this.container = container;
        }
        return this;
    }
    _constructor.extend(TESCO.UI.Flyout.Transient);

    //  public default attributes
    _constructor.prototype.NAME = "TESCO.UI.Flyout.Navigation";
    

    //  public methods
    _constructor.prototype.load = function(e, id) {
        //  assemble url and pass back to base
        var _entity = {
            "request": {
                "navigationOption": {
                    "id": TESCO.UI.Flyout.key,
                    "allOptions": TESCO.system.DOM.node.getElementsByClassName(this.container, "flyout")[0].id.split("-")[1] || null
                }
            }
        }
        _constructor.base.load.call(this, e, id, _urls[e.type], _entity);
    }

    //  return _constructor as function pointer
    return _constructor;
})();