﻿Type.registerNamespace("TrackMyERO");

TrackMyERO.CustomERO = function(element) {
    /// <summary>
    /// Custom map popups (ERO) functionality   
    /// </summary>
    /// <param name="element">The custom ERO element to show</param>
    
    this._closeelement;
    this._triggerelementID;
    this._contentelementID;
    this._map;
    this._enabled;

    this._CentreX;
    this._CentreY;
    this._PopupDelay;

    this._currentpinInfoBox = null;
    this._isvisible = false;

    this._PinClickDelegate = null;
    this._CloseDelegate = null;

    this._popuptimer;
    this._currentTriggeredID;

    TrackMyERO.CustomERO.initializeBase(this, [element])
}

TrackMyERO.CustomERO.prototype = {

    initialize: function() {
        /// <summary>
        ///   Initialises the Control.
        /// </summary>

        //Setup the close button for the ERO
        this._CloseDelegate = Function.createDelegate(this, this._HidePanel);
        $addHandler(this._closeelement, "click", this._CloseDelegate);

        //turn off the standard popup and attach our custom handler
        this._PinClickDelegate = Function.createDelegate(this, this._onMouseClick);
        this._map.AttachEvent("onclick", this._PinClickDelegate);

        //Setup a timer to allow a user to quick mouseover pins without triggering an expensive AJAX data call
        this._popuptimer = new Sys.Timer();
        this._popuptimer.initialize();
        this._popuptimer.set_interval(this._PopupDelay);
        this._popuptimer.add_tick(Function.createDelegate(this, this._onTimerTick));
        this._popuptimer.set_enabled(false);

        //turn off the standard popup and attach our custom handler
        this._map.AttachEvent("onmouseover", Function.createDelegate(this, this._onMouseOver));
        this._map.AttachEvent("onmouseout", Function.createDelegate(this, this._onMouseOut));

        //watch out for the start of a pan event, need to clear our ERO
        this._map.AttachEvent("onstartpan", Function.createDelegate(this, this.NotifyDataChange));
    },

    NotifyDataChange: function() {
        /// <summary>
        ///   Call to notify that the data on the map has changed, the ERO is hidden and values reset
        /// </summary>     
        this._currentpinInfoBox = null
        this._HidePanel();
    },

    _onMouseOver: function(e) {
        /// <summary>
        ///   Receives mouse over event from VE, Start a timer to see if the user stays over the pin
        /// </summary>  
        /// <param name="e">The MapEvent object</param>         
        if (this._enabled && e.elementID) {
            this._popuptimer.set_enabled(false);
            this._currentTriggeredID = e.elementID;
            this._popuptimer.set_enabled(true);
            return true;
        }
    },

    _onMouseOut: function(e) {
        /// <summary>
        ///   Receives mouse out event from VE, the user may have moused off the event before the time specified to launch the ERO
        /// </summary>  
        /// <param name="e">The MapEvent object</param>         
        if (this._enabled && e.elementID) {
            this._popuptimer.set_enabled(false);
            return true;
        }
    },

    _onMouseClick: function(e) {
        /// <summary>
        ///   Receives mouse click event from VE, launch ERO straight away.
        /// </summary>  
        /// <param name="e">The MapEvent object</param>
        this._popuptimer.set_enabled(false);
        if (this._enabled && e.elementID) {
            var popupShape = this._map.GetShapeByID(e.elementID)
            if (popupShape) {
                this._LoadInfobox(popupShape);
            }
            return true;
        }
    },

    _onTimerTick: function() {
        /// <summary>
        ///   Triggered on timer, if the user stayed over a pin for the duration we launch the ERO
        /// </summary>   
        this._popuptimer.set_enabled(false);
        if (this._enabled && this._currentTriggeredID) {
            var popupShape = this._map.GetShapeByID(this._currentTriggeredID)
            if (popupShape) {
                this._LoadInfobox(popupShape);
            }
            return true;
        }
    },

    _LoadInfobox: function(popupShape) {
        /// <summary>
        ///   Launch the ERO
        /// </summary>
        /// <param name="popupShape">The VEShape object</param>

        //Check this is a valid shape to launch a popup (GetMoreInfoURL must be populated)
        if (popupShape.GetMoreInfoURL() != "") {
            //verify new pin or else we show where the user left off (accidently closed it)
            if (this._currentpinInfoBox == null || popupShape.GetMoreInfoURL() != this._currentpinInfoBox.GetMoreInfoURL()) {
                this._HidePanel();

                //set current pin, clear all existing data
                this._currentpinInfoBox = popupShape;

                //get the content for the pin.
                this._GetData();
            }
            if (!this._isvisible) {
                this._isvisible = true;
                var point;

                //get point
                if (this._currentpinInfoBox.GetType() == VEShapeType.Pushpin) {
                    point = this._map.LatLongToPixel(this._currentpinInfoBox.GetPoints()[0]);
                } else {
                    point = this._map.LatLongToPixel(this._currentpinInfoBox.GetIconAnchor());
                }

                //build up the style classname
                var cssStyle = "infobox";
                if (point.y > this._CentreY) {
                    cssStyle += "T";
                } else {
                    cssStyle += "T";
                }
                if (point.x > this._CentreX) {
                    cssStyle += "L";
                } else {
                    cssStyle += "R";
                }
                //remove the old ones
                Sys.UI.DomElement.removeCssClass(this.get_element(), "infoboxTL")
                Sys.UI.DomElement.removeCssClass(this.get_element(), "infoboxBL")
                Sys.UI.DomElement.removeCssClass(this.get_element(), "infoboxTR")
                Sys.UI.DomElement.removeCssClass(this.get_element(), "infoboxBR")
                //append the new style
                Sys.UI.DomElement.addCssClass(this.get_element(), cssStyle)

                //set location
                this.get_element().style.left = point.x + "px";
                this.get_element().style.top = point.y + "px";
                //finally we show the ERO
                this.get_element().style.display = "block";
                this._GetData();
            }
        }
    },

    _HidePanel: function() {
        /// <summary>
        ///   Hide the ERO
        /// </summary> 
        this.get_element().style.display = "none";
        //Hide the old content
        if (this._contentelementID) {
            $get(this._contentelementID).style.display = "none";
            //$get(this._contentelementID).innerHTML = "";
        }
        this._isvisible = false;
    },

    _GetData: function() {
        /// <summary>
        ///   Get the data for the current pin
        /// </summary>     
        if (this._triggerelementID) {
            var _triggerelement = $get(this._triggerelementID);
            //Trigger the updatepanel to get content from server by setting the Key in field
            _triggerelement.value = this._currentpinInfoBox.GetMoreInfoURL();
            _triggerelement.onchange();
        }
    },

    //property getters and setters:

    //The VE Map Object
    get_map: function() {
        return this._map;
    },
    set_map: function(value) {
        this._map = value;
    },

    //The centre postion X pixels, 
    //typically the centre of the map used to determine what quadrant style to apply
    get_CentreX: function() {
        return this._CentreX;
    },
    set_CentreX: function(value) {
        this._CentreX = value;
    },

    //The centre postion Y pixels, 
    //typically the centre of the map used to determine what quadrant style to apply
    get_CentreY: function() {
        return this._CentreY;
    },
    set_CentreY: function(value) {
        this._CentreY = value;
    },

    //The time in ms the user must hover over a pin before the ERO triggers data request and is shown
    get_PopupDelay: function() {
        return this._PopupDelay;
    },
    set_PopupDelay: function(value) {
        this._PopupDelay = value;
    },

    //The element to trigger for the data
    //This is an ID as the actual element changes in an updatepanel
    get_triggerelementID: function() {
        return this._triggerelementID;
    },
    set_triggerelementID: function(value) {
        this._triggerelementID = value;
    },

    //The content section
    //This is an ID as the actual element changes in an updatepanel
    get_contentelementID: function() {
        return this._contentelementID;
    },
    set_contentelementID: function(value) {
        this._contentelementID = value;
    },

    //The close button to bind the close event too
    get_closeelement: function() {
        return this._closeelement;
    },
    set_closeelement: function(value) {
        this._closeelement = value;
    },

    //Simple property to turn off the ERO if needed
    get_Enabled: function() {
        return this._enabled;
    },
    set_Enabled: function(value) {
        this._enabled = value;
    },

    //clean up all events
    //note the VEMAP doesn't like to detach events here so we ignore these.
    dispose: function() {
        $removeHandler(this._closeelement, "click", this._CloseDelegate);
        this._PinClickDelegate = null;
        this._CloseDelegate = null;
        TrackMyERO.CustomERO.callBaseMethod(this, 'dispose');
    }
}

TrackMyERO.CustomERO.registerClass('TrackMyERO.CustomERO', Sys.UI.Behavior, Sys.IDisposable);

if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();