﻿Type.registerNamespace("fdi");

fdi.MapControls = function (element) {
    this._zoom = 1;
    this._minZoom = 1;
    this._maxZoom = 19;
    this._panby = 15;
    this._mousex = 0;
    this._mousey = 0;
    this._compassmouseheld = false;
    this._mapstyle = "r";
    var _self; //used for settimeout callback

    fdi.MapControls.initializeBase(this, [element]);
}

fdi.MapControls.prototype = {

    initialize: function () {
        //create controls
        this._createControls();
        //setup events
        this._attachEvents();
        _self = this;
    },
    //methods
    //#region
    _createControls: function () {
        this._createSlider();
        this._attachEvents();
    },

    _createSlider: function () {
        //create slider control
        $("#slider").slider({
            orientation: "vertical",
            range: "max",
            min: this._minZoom,
            max: this._maxZoom,
            value: this._zoom,
            step: 1,
            slide: new Function.createDelegate(this, this._slideChanged)
        });

        //setup map control fades
        $('#' + this.get_element().id + '> *:not(#compass)').fadeTo(0, 0.7);
        $('#' + this.get_element().id + '> *[id$=bar]').fadeTo(0, 0.5);
        //fade in
        $('*[id$=bar]', this.get_element()).mouseenter(function () {
            $('*:not(#compass):not([id$=bar])', $(this).parent()).fadeTo('medium', 1);
            $('*[id$=bar]', $(this).parent()).fadeTo('medium', 0.7);
        });
        //fade out
        $('*[id$=bar]', this.get_element()).mouseleave(function () {
            $('*:not(#compass):not([id$=bar])', $(this).parent()).fadeTo('medium', 0.7);
            $('*[id$=bar]', $(this).parent()).fadeTo('medium', 0.5);
        });

        //attach button events
        $('#btnzoomin').click(new Function.createDelegate(this, this._zoomClicked));

        //attach button events
        $('#btnzoomout').click(new Function.createDelegate(this, this._zoomClicked));
    },


    _attachEvents: function () {
        //attach compas mousedown and up events
        $('#compass').mousedown(new Function.createDelegate(this, this._compassMouseDown)).mouseup(new Function.createDelegate(this, this._compassMouseUp)).mousemove(new Function.createDelegate(this, this._compassMouseMove)).mouseleave(new Function.createDelegate(this, this._compassMouseUp));
        $("#mapstyles a").click(new Function.createDelegate(this, this._mapstyleClicked));
    },


    //works out how much to pan by depending on the mouses position relative
    //to the compass centre
    _calculatePan: function (mousex, mousey) {
        //get mouse position relative to compass center
        var cw = $("#compass").width();
        var ch = $("#compass").height();

        //get compass top left position
        var os = $("#compass").offset();
        var cx = os.left;
        var cy = os.top;

        //work out width / height mouse is offset from compass centre
        var ctrx = mousex - (cx + cw / 2); //if positive pan right
        var ctry = mousey - (cy + ch / 2); //if positive pan down 

        //pan by the % mouse is offset of compass width and height
        var px = this._panby * (ctrx / (cw / 2));
        var py = this._panby * (ctry / (ch / 2));

        return { x: Math.round(px), y: Math.round(py) };
    },

    _compassPan: function () {
        if (_self._compassmouseheld) {
            //calculate pan ammount
            var xy = _self._calculatePan(_self._mousex, _self._mousey);

            //fire pan event
            _self._raiseEvent('onPan', new fdi.SelectionChangedEventArgs(xy));

            //wait then call again until mouse _compassmouseheld=false

            setTimeout(_self._compassPan, 500);
        }
    },
    //selects the correct map style button
    _selectMapStyleButton: function (style) {
        switch (style) {
            case "a":
                $("#btnaerial a").addClass("selected");
                $("#btnroad a").removeClass("selected");
                break;
            case "r":
                $("#btnroad a").addClass("selected");
                $("#btnaerial a").removeClass("selected");
                break;
        }
    },
    //#endregion

    //properties
    //#region

    //#endregion
    get_Zoom: function () {
        return this._zoom;
    },
    set_Zoom: function (v) {
        this._zoom = v;
        if ($('#slider').slider) $('#slider').slider('option', 'value', this._zoom);
    },
    get_MinZoom: function () {
        return this._minZoom;
    },
    set_MinZoom: function (v) {
        this._minZoom = v;
    },
    get_MaxZoom: function () {
        return this._maxZoom;
    },
    set_MaxZoom: function (v) {
        this._maxZoom = v;
    },
    get_MapStyle: function () {
        return this._mapstyle;
    },
    set_MapStyle: function (v) {
        this._mapstyle = v;
        this._selectMapStyleButton();
    },
    //events
    //#region
    //event for zoom changed
    add_zoomChanged: function (handler) {
        this.get_events().addHandler('zoomChanged', handler);
    },
    remove_zoomChanged: function (handler) {
        this.get_events().removeHandler('zoomChanged', handler);
    },
    add_onPan: function (handler) {
        this.get_events().addHandler('onPan', handler);
    },
    remove_onPan: function (handler) {
        this.get_events().removeHandler('onPan', handler);
    },
    add_mapstyleChanged: function (handler) {
        this.get_events().addHandler('mapstyleChanged', handler);
    },
    remove_mapstyleChanged: function (handler) {
        this.get_events().removeHandler('mapstyleChanged', handler);
    },
    _raiseEvent: function (eventName, eventArgs) {
        var handler = this.get_events().getHandler(eventName);
        if (handler) {
            if (!eventArgs) {
                eventArgs = Sys.EventArgs.Empty;
            }
            handler(this, eventArgs);
        }
    },
    //#endregion

    //event handlers
    //#region
    //handles the slider changed event
    _slideChanged: function (event, ui) {
        //raise zoom changed event
        this._raiseEvent('zoomChanged', new fdi.SelectionChangedEventArgs(ui.value));
    },
    //handles the zoom buttons click events
    _zoomClicked: function (e) {
        //getter
        var value = $('#slider').slider('option', 'value');

        //check which element was clicked
        switch (e.target.id) {
            case "btnzoomin":
                //increase slider value by one
                if (value < 19) value++;
                break;
            case "btnzoomout":
                if (value > 1) value--;
                break;
        }

        //setter
        $('#slider').slider('option', 'value', value);

        //raise zoom changed event
        this._raiseEvent('zoomChanged', new fdi.SelectionChangedEventArgs(value));
    },

    _compassMouseDown: function (e) {
        this._compassmouseheld = true;
        this._mousex = e.pageX;
        this._mousey = e.pageY;

        //pan
        this._compassPan({ context: this });
    },
    _compassMouseUp: function () {
        this._compassmouseheld = false;
    },
    _compassMouseMove: function (e) {
        this._mousex = e.pageX;
        this._mousey = e.pageY;

        //pan if mouse held down
        if (this._compassmouseheld) this._compassPan({ context: this });
    },
    _mapstyleClicked: function (e) {
        switch (e.target.parentNode.id) {
            case "btnroad":
                this._mapstyle = "r";
                break;
            case "btnaerial":
                this._mapstyle = "a";
                break;
            default:
                this._mapstyle = "";
                break
        }
        if (this._mapstyle != "") {
            this._selectMapStyleButton(this._mapstyle);
            this._raiseEvent('mapstyleChanged', new fdi.SelectionChangedEventArgs(this._mapstyle));
        }
        return false;

    },
    //#endregion


    dispose: function () {

    }
}

fdi.MapControls.registerClass('fdi.MapControls', Sys.UI.Control);


// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
        

//selectionchange event arg
fdi.SelectionChangedEventArgs = function (newselection) {
    if (arguments.length !== 1) throw Error.parameterCount();

    //Calling the base class constructor
    fdi.SelectionChangedEventArgs.initializeBase(this);
    this._newselection = newselection;
}

fdi.SelectionChangedEventArgs.prototype =
{
    get_newSelection: function () {
        if (arguments.length !== 0) throw Error.parameterCount();

        return this._newselection;
    }
}

fdi.SelectionChangedEventArgs.registerClass('fdi.SelectionChangedEventArgs', Sys.EventArgs);
