﻿general.namespace('SW.Controls');

(function () {

    var SavedViews = SW.Controls.SavedViews = function(div, popupMenu, initialSavedViewsJSON, isUserLoggedIn) {
            
            this.views = [];  // starts empty; setViewsFromJSON() is called in the region request handler (because the regions are required to deserialize)
            this.div = $id(div);
            this.popupMenu = $id(popupMenu);
            this.popupMenu.style.display = 'none'; // necessary for menu to pop-up upon first mouseover
            this.savedViewList = $id('saved-views-list'); // ul
            this.savedViewTitle = $id('saved-views-title');
            this.viewNameTextField = $id('save-search-textfield');
            this.isUserLoggedIn = isUserLoggedIn;

            if (initialSavedViewsJSON) {
                this.setViewsFromJSON(initialSavedViewsJSON);
            }
            this.createAddSavedViewDialog();
            
            var me = this;
            
            general.addListener(this.div, 'mouseout', function (evt) {
                var entered = evt.relatedTarget || evt.toElement;
                    
                if (!general.isNodeOrChildOf(entered, me.div)) {
                    me.savedViewTitle.style.color = 'white';
                    me.popupMenu.style.display = 'none';
                }
                YAHOO.util.Event.preventDefault(evt);                
                return false;
            });
            
            general.addListener(this.div, 'mouseover', function (evt) {
                var entered = evt.target || evt.srcElement;
                
                if (general.isNodeOrChildOf(entered, me.div)
                        && me.popupMenu.style.display === 'none') {
                    me.savedViewTitle.style.color = '#FFCC66';
                }
                YAHOO.util.Event.preventDefault(evt);
                return false;
            });
            
            general.addListener(this.div, 'mousedown', function (evt) {
                var target = evt.target || evt.srcElement;
                
                if (!general.isNodeOrChildOf(target, me.savedViewList)
                        && me.popupMenu.style.display === 'none') {
                    if (me.isUserLoggedIn) me.updateViewMenu();
                    me.popupMenu.style.display = 'block';
                }
                
                YAHOO.util.Event.preventDefault(evt);
                return false;
            });
            
            general.addListener(this.savedViewList, 'mousedown', function (evt) {
                var target = evt.target || evt.srcElement;
                
                if (target.buttonType) {
                    if (target.buttonType === 'delete') {
                        me.deleteView(target.buttonIdx);
                    }
                    else if (target.buttonType === 'view') {
                        me.goToView(target.buttonIdx);
                        me.popupMenu.style.display = 'none';
                    }
                }
                
                YAHOO.util.Event.preventDefault(evt);
                return false;
            });
        };
        SavedViews.prototype.constructor = SavedViews;
        
        
        /* returns name of view if this state already is saved; otherwise return empty string */
        SavedViews.prototype.savedViewAlreadyExists = function (state) {
            var views = this.views;
            // check if state already exists in saved views
            for (var i = 0; i < views.length; i++) {
                if (SWMap.historyControl.areStatesEqual(views[i].state, state)) {
                    return views[i].name;
                }
            }
            return '';
        };
        
        /* returns true if a saved view already has that name */
        SavedViews.prototype.savedViewNameAlreadyExists = function (name) {
            var views = this.views;
            // check if state already exists in saved views
            for (var i = 0; i < views.length; i++) {
                if (views[i].name === name) {
                    return true;
                }
            }
            return false;
        };
        
        
        /**/
        SavedViews.prototype.createAddSavedViewDialog = function () {
            var me = this;
            
            var text, errorMessage, saveButton;
                        
            var dialog = general.createOverlayWindow(
                'addSavedViewNamePrompt',
                $C('div', {padding: '20px', width: '363px'},
                    $C('div', null, {html: 'Enter a name for this view:'},
                        text = 
                        $C('input', {width: '356px', marginTop: '12px'})
                    ),
                    $C('table', {marginTop: '10px'},
                        $C('tr',
                            errorMessage = 
                            $C('td', {width: '302px', color: 'red', fontWeight: 'bold'}),
                            $C('td',
                                saveButton = 
                                $C('button', {width: '55px', height: '30px'}, {html: 'Save'})
                            )
                        )
                    )
                ),
                400,
                123,
                ["map-container", "tr", "tr"]
            );
            dialog.hideEvent.subscribe(function (evt) {
                text.blur();
            });
            
            
            var alreadyExistsMessage, alreadyExistsButton;
            
            var alreadyExistsAlert = general.createOverlayWindow(
                'savedViewAlreadyExistsAlert',
                $C('div', {marginTop: '34px', marginLeft: '20px', width: '363px'},
                    alreadyExistsMessage =
                    $C('div'),
                    alreadyExistsButton =
                    $C('button', {width: '55px', height: '30px', cssFloat: 'right', marginTop: '12px', marginRight: '7px'}, {html: 'OK'})
                ),
                400,
                115,
                ["map-container", "tr", "tr"]
            );
            
            
            function addView () {
                var name = text.value;
                
                if (name === '') {
                    errorMessage.innerHTML = 'Cannot be blank.';
                }
                else if (me.savedViewNameAlreadyExists(name)) {
                    errorMessage.innerHTML = 'Another saved view already uses that name.';
                }
                else {
                    me.views.push({
                        name: name,
                        state: SWMap.historyControl.getState()
                    });                            
                    
                    me.postViews(me.views);
                    me.updateViewMenu();
                    dialog.hide();
                }   
            }
            
            general.addListener(saveButton, 'mousedown', function (evt) {
                 addView();
                 YAHOO.util.Event.preventDefault(evt);
                 return false;
            });
            
            general.addListener(alreadyExistsButton, 'mousedown', function (evt) {
                 alreadyExistsAlert.hide();
                 YAHOO.util.Event.preventDefault(evt);
                 return false;
            });
            
            general.addListener(text, 'keypress', function (evt) {
                if (evt.keyCode === 13) {
                    addView();
                    YAHOO.util.Event.preventDefault(evt);
                    return false;
                }
            });
            
            if ($id('save-search-button')) {
                general.addListener('save-search-button', 'mousedown', function (evt) {
                    var state = SWMap.historyControl.getState();
                    
                    var existingViewName = me.savedViewAlreadyExists(state);
                    if (existingViewName !== '') {
                        alreadyExistsMessage.innerHTML = 'This view is already saved as "' + existingViewName + '".';
                        alreadyExistsAlert.show();
                    }
                    else {
                        errorMessage.innerHTML = ' ';
                        var name = me.getDefaultViewName();
                        if (me.savedViewNameAlreadyExists(name)) {
                            name = '';
                        }
                        text.value = name;
                        dialog.show();
                        text.focus();
                    }
                    
                    YAHOO.util.Event.preventDefault(evt);
                    return false;
                });
            }
        };        
        
        /**/
        SavedViews.prototype.postViews = function (views) {
            // pass in the current time (it is a unixtime in milliseconds) so that the webservice can deal with races
            YAHOO.util.Connect.asyncRequest(
                'POST',
                '/WebServices/SavedViews.asmx/UpdateUserSavedViews?r=' + general.rand(),
                {}, // no handlers
                JSON.encode({
                    savedViews: JSON.encode(views), // the service expects JSON within JSON because it only deals with the savedViews as a string
                    saveTime: new Date().getTime()
                })
            );
        };
        
        if (typeof GMap !== 'undefined') {
            SavedViews.MAP_TYPES_BY_SHORT_NAME = {
                Map: G_NORMAL_MAP,
                Sat: G_SATELLITE_MAP,
                Hyb: G_HYBRID_MAP
            };
        }
        
        /**/
        SavedViews.prototype.setViewsFromJSON = function (jsonString) {
            var views = general.deserializeJSON(jsonString, true);  // don't use JSON.decode: it creates strange conflicts with ajax.net service calls
            this.convertFromOldFormat(views);
            this.views = views || [];  // new user doesn't have any views, so views will be null
            this.updateViewMenu();
        };
        
        
        /* modifies views in place */
        SavedViews.prototype.convertFromOldFormat = function (views) {
            var needsUpdate = false;
            for (var i in views) {
                var view = views[i];
                if (!view.state) { // new format has .state but old doesn't
                    needsUpdate = true;
                    var replacement = {};
                    replacement.name = view.name;
                    replacement.state = SWMap.historyControl.encodeState(
                        view.centerLat,
                        view.centerLng,
                        view.zoom,
                        view.animatedRegionId,
                        view.animationType,
                        view.markerType,
                        view.mapTypeName
                    );
                    views[i] = replacement;
                }
                if (view.state.split('_').length === 7) {
                    needsUpdate = true;
                    view.state += '_-1';
                }
            }
            
            if (needsUpdate) {
                this.postViews(views);
            }
        };
                
        /**/
        SavedViews.prototype.deleteView = function (idx) {
            this.views.splice(idx, 1);
            
            this.postViews(this.views);
            this.updateViewMenu();
        };        
        
        /**/
        SavedViews.prototype.updateViewMenu = function () {
            var listItems = [];
            
            for (var i in this.views) {
                var name = this.views[i].name;
                
                var viewButton, deleteButton;
                listItems.push(
                    $C('div',
                        viewButton =
                        $C('a', {overflow: 'hidden'}, {href: '#', title: name, classes: 'name-saved-view', html: name}),
                        deleteButton =
                        $C('img', null, {
                            classes: 'delete-saved-view',
                            src: '/assets/images/icn-trash-small.gif',
                            alt: 'Remove "' + name + '" from your list'
                        })
                    )
                )
                
                viewButton.buttonType = 'view';
                viewButton.buttonIdx = i;
                
                deleteButton.buttonType = 'delete';
                deleteButton.buttonIdx = i;
            }
            
            general.replaceAllChildren(this.savedViewList, listItems);
        };        
        
        /**/
        SavedViews.prototype.goToView = function (idx) {
            var view = this.views[idx];
            SWMap.perspectiveView.close(); // the perspective view might be open
            var state = SWMap.historyControl.parseState(view.state);
            SWMap.historyControl.goToState(state, false);
        };        
        
        /**/
        SavedViews.prototype.getDefaultViewName = function () {
            var defaultViewName;
            
            if (SWMap.animationControl.animation.isPerspective) {
                defaultViewName = '3D ' + SWMap.perspectiveView.perspectiveName;
            }
            else {
                var map = SWMap.map;
                var zoom = map.getZoom();
                var center = map.getCenter();
                defaultViewName = center.getTightestContainingRegion(zoom).name;
                
                if (SWMap.animationControl.currentType === 'off') {
                    center = new GLatLng(center.lat(), center.lng(), false); // make sure center is bounded
                
                    var lat = center.lat();
                    lat = Math.abs(lat.toFixed(2)) + '\u00b0' + ((lat >= 0) ? 'N' : 'S');
                    
                    var lng = center.lng();
                    lng = Math.abs(lng.toFixed(2)) + '\u00b0' + ((lng >= 0) ? 'E' : 'W');
                
                    defaultViewName += '  ' + lat + '  ' + lng;
                }
            }
            
            return defaultViewName;
        };
})();