/**
 * Permalink.js: The following file manages permalinks.
 * NOTE: This adds a javascript pseudo-thread via a setInterval function.
 *
 */



HyperCities.linkController = function () {
    var _id = "[Hypercities Link Controller] ";
    var _timingInterval = 1000; // Number of miliiseconds between executions of this process.
    var _linkUpdateDelay = 3000; // The default wait for a link. Set to 0 once the first link has been parsed, or after 5 seconds.
    // This is necessary because the application is loaded asynchronously.
    var _lastHash = "";
    var _systemHashes = ["#", "#search", "#login", "#worldMap"];
    var _threadHandle; // identifier returned by setInterval() for _pollHash thread
    //var _showNarrative = true;

    /**
     * This function is the pseudo-thread. It checks if a new permalink has been
     * entered, and if so, applies it.
     *
     */
    var _pollHash = function () {
        //HyperCities.debug(_id + " Show narrative? " + _showNarrative);
        // Commented out because it overpopulates the Firebug console.
        //HyperCities.debug (_id + "Checking for permalink.");
        if (_lastHash == "" && window.location.search != "") {
            // Do not parse hashes intended for other parts of the application.
            //if (_systemHashes.indexOf(window.location.hash) != -1 ) return;
            if ($.inArray(window.location.hash, _systemHashes) != -1) return;
            _lastHash = window.location.search.substr(1);
            // HyperCities.debug (_id + "Found snapshot or permalink");
            _handlePermalink(window.location.search.toString().substr(1));
            return;
        }

        // Do not parse hashes intended for other parts of the application.
        // if (_systemHashes.indexOf(window.location.hash) !== -1 ) return;
        if ($.inArray(window.location.hash, _systemHashes) != -1 ) return;
        // get new hash and remove hash from the beginning of it
        var currentHash = window.location.hash.substr(1);
        // Because the view may move, the user may want to return to the previous view using a link

        // If the hash has not changed since last polled, do nothing
        if (currentHash == _lastHash || currentHash == "") return;
        // handle coordinates as ll, z
        if (currentHash.indexOf('ll') == 0) {
            _lastHash = currentHash;
            _zoomToCoords(currentHash);
            return;
        }


        // Otherwise, we parse it
        // If it's a saved snapshot, parse that


        if (currentHash.indexOf("++st++") == 1) handleSnapshot(currentHash);
        else {
            _lastHash = currentHash;
            _handlePermalink(currentHash);
        }
    //_showNarrative = false;
    }

    var _zoomToCoords = function ($hash) {
        //HyperCities.debug (_id + "Coordinates found.")
        var lat = parseFloat($hash.substr($hash.indexOf("=") + 1, $hash.indexOf(",") - 1));
        if ($hash.indexOf("z") != -1) {
            var zoom = parseInt($hash.substr($hash.indexOf("=", $hash.indexOf("z")) + 1));
            HyperCities.debug($hash.substr($hash.indexOf("=", $hash.indexOf("z")) + 1));
            var lng = parseFloat($hash.substr($hash.indexOf(",") + 1, $hash.indexOf("&z") - 1 ));
            if (zoom == HyperCities.mainMap.getZoom()) HyperCities.mainMap.panTo(new GLatLng(lat, lng));
            else HyperCities.mainMap.setCenter(new GLatLng(lat, lng), zoom);
            return;
        } else {
            var lng = parseFloat($hash.substr($hash.indexOf(",") + 1));
            HyperCities.debug($hash.substr($hash.indexOf(",")));
            var zoom = HyperCities.mainMap.getZoom();
            HyperCities.mainMap.panTo(new GLatLng(lat, lng));
            return;
        }

        //HyperCities.debug($hash.substr($hash.indexOf("="), $hash.indexOf(",")));
        HyperCities.debug(_id + "Lat: " + lat + " Lon: " + lng + " Zoom: " + zoom);
        HyperCities.mainMap.setCenter(new GLatLng(lat, lng), zoom);
    };

    var _queryParse = function (qString) {
        // If a user has just entered a city name
        // Changed to allow both anchors and query strings
        //var qString = $hash;
        // If it's a snapshot
        if (qString.indexOf('#') != -1) qString = qString.split('#')[1];
        if (qString.indexOf('/') != -1) {
            return {
                itemType : qString.split('/')[0],
                itemId : qString.split('/')[1]
            }
        }
        if (qString.indexOf('snapshots/') != -1) {
            return {
                itemType : 'snapshot',
                itemId : qString.substr(qString.indexOf('/') + 1)
            }
            // hand off

        }
        //if (location.search && location.search != '') qString = location.search.substr(1);
        //else if (location.hash && location.hash != '' && location.hash != '#search' && location.hash != '#login') qString = location.hash.substr(1);
        if (qString.indexOf('&') == -1)
        {
            HyperCities.debug(_id + " Assuming city was specified in URL.");
            return {
                item_type : 'city',
                city_name : qString
            };
        } // end city parsing
        var query = new Array();
        // remove the Question Mark at the beginning
        if (qString.indexOf('&')) {
            var pairs = qString.split("&");
        } else {
            var pairs = qString;
        }
        // allowable keywords
        var allowableVars = new Array("city", "ne_lat", "ne_lon", "sw_lat", "zoom",
            "sw_lon", "object_type", "item_id" // NOTE: item_id can refer to objects or maps, or any other item we pull
            ); // TBC ...
        for (var i in pairs) {
            var keyval = pairs[i].split("=");
            query[keyval[0]] = keyval[1];
        // necessary because $.ajax functions require maps

        } // end for (i in pairs)
        var params = {
            // location
            neLat:query['neLat'],
            neLon: query["ne_lon"],
            swLat:query["sw_lat"],
            swLon:query['sw_lon'],
            centerLat: query['center_lat'],
            centerLon: query['center_lon'],
            // Style
            zoom:query["zoom"],
            itemType: query['item_type'],
            itemId: query['item_id']
        }
        return query;
    }

    var _handlePermalink = function ($hash) {
        HyperCities.debug (_id + "Handling permalink " + $hash);
        //HyperCities.mainMap.closeHCInfoWindow();
        //HyperCities.session.set("infoWin", null);
        //HyperCities.session.set("maxInfoWin", null);
        // TODO: edit this function so that it uses what is passed to it ($hash) rather than browser object
        var params = new Object();
        var query = _queryParse($hash);
        HyperCities.session.permalinkedItems.id = query['item_id'];
        HyperCities.session.permalinkedItems.type = query['item_type'];

        if (typeof(query.itemType) !== 'undefined') {
            switch (query.itemType) {
                case 'objects':
                    //HyperCities.debug ( _id + ' Getting permalinked object.');
                    // get coordinates from database and center on these
                    //this.permalinkedItems.id = query['item_id'];
                    params = {
                        object_id   : query.itemId
                    }
                    //HyperCities.debug(_id + " Sending get-object query.");
                    //HyperCities.mainMap.closeHCInfoWindow(true);

                    //HyperCities.intelliList.reset();
                    //HyperCities.mainMap.clearOverlays();
                    $.post("./getObject.php", params, _objectPermalinkCallback, "xml");
                    break;
                case 'collections':
                    //var helpPanel = $(document.createElement("div"));
                    
                    var __openHelpPanel = function ($data) {
                        HyperCities.debug(_id + "Showing help panel.");
                        $("#helpPanelWrapper").toggle();
                        $("#helpPanel").append($($data));
                        //HyperCities.debug($($data).html());
                        $("#helpPanel").fadeIn();
                        $("#helpPanelClose").click(function () {$("#helpPanelWrapper").fadeOut();});
                    }

                    // TODO: Add if query.itemId == TUA collection id number
                    if ($.cookie("sawCollectionHelpscreen") != "true" && 
query.itemId == 16147 ) {
                        //$.post("./quickstart/QS_NarrativeMode.html", null, __openHelpPanel, "html");
                        $("#helpPanelFrame > iframe").attr('src', "./quickstart/QuickStart.html");
                        
                        
                        //$("#helpPanel").append(helpFrame);
                        //HyperCities.debug($($data).html());
                        $("#helpPanelWrapper").toggle();
                        $("#helpPanel").fadeIn();
                        $("#helpPanelClose").click(function () {$("#helpPanelWrapper").fadeOut();});
                    }
                    if (query.itemId == 15165) {
                        $("#helpPanelFrame > iframe").attr('src', "./quickstart/QuickStart_GM.html");


                        //$("#helpPanel").append(helpFrame);
                        //HyperCities.debug($($data).html());
                        $("#helpPanelWrapper").toggle();
                        $("#helpPanel").fadeIn();
                        $("#helpPanelClose").click(function () {$("#helpPanelWrapper").fadeOut();});
                    }
                        
                    params.cid = parseInt(query.itemId);
                    params.func = 'narrativePanel.getNarrative';
                    //			HyperCities.debug(_id + " Collection id number: " + params.cid);
                    // Set option zoom to ture,
                    // this method will auto zoom the map to the extent of collection.
                    // Because we don't have parentId information,
                    // set it to null will disable the delete button in narritive Panel
                    setTimeout(function() {
                        HyperCities.narrativePanel.load(null, params.cid, {
                            zoom: true
                        });
                    }, 1000);
                    //$.cookie("sawCollectionHelpscreen", "true", {expires: 60});
                    break;
               case 'city':
                    var zoomToCity = function () {
                        var city = HyperCities.city.getCityByName(query.city_name.replace(/_/, " "));
                        if (typeof(city) == 'undefined') alert ("Invalid City Name.");
                        HyperCities.mainMap.removeCities();
                        HyperCities.mainMap.setCenter(city.defaultCenter, 14);
                    }
                    HyperCities.debug(_id + " Looking for " + query.city_name);
                    HyperCities.session.set("city", query.city_name.replace(/_/, " "));

                    if (_linkUpdateDelay != 0) {
                        setTimeout (zoomToCity, _linkUpdateDelay);
                    }
                    else {
                        zoomToCity();
                    }
                   break;
               case 'maps':
                   break;
               case 'snapshots':
                    HyperCities.debug(_id + "Getting snapshot number " + query.itemId);
                    HyperCities.session.loadSnapshot(query.itemId);
                    break;
               default:
                   alert ("Invalid item type.");
                   break;
            } // end switch (query.item_type)
            // Remove cities from map
            HyperCities.mainMap.removeCities();
            return; // leave function now -- permalink has been dispatched
        } // end checking if item is new-style permalink

        if (query['item_type'] == 'object') {
            //HyperCities.mainMap.closeHCInfoWindow(false);
            HyperCities.mainMap.closeHCInfoWindow();
            //HyperCities.debug ( _id + ' Getting permalinked object.');
            // get coordinates from database and center on these
            //this.permalinkedItems.id = query['item_id'];

            var params = {
                object_id   : query['item_id']
            }
            //HyperCities.debug(_id + " Sending get-object query.");
            $.post("./getObject.php", params, HyperCities.collectionList.addObject, "xml");
        //HyperCities.debug(_id + "Permalink query sent.");
        }
        else if (query.item_type == 'city')
        {
            // TODO: Delete the following closure; it is not used
            var zoomToCity = function () {
                //HyperCities.debug (_id + "Working on finding a city ... ")
                var city = HyperCities.city.getCityByName(query.city_name.replace(/_/, " "));
                if (typeof(city) == 'undefined') alert ("Invalid City Name.");
                //HyperCities.debug(_id + "City found" + city.name);
                //bounds = new GLatLngBounds (new GLatLng(city.swLat, city.swLon), new GLatLng(city.neLat, city.neLon));
                //HyperCities.mainMap.setCenter(bounds.getCenter(), 10);
                HyperCities.mainMap.removeCities();
                HyperCities.mainMap.setCenter(city.defaultCenter, 14);
            }

            /*if (query.city_name == 'worldMap' || query.city_name == 'search' || query.city_name == 'login') {
            // It's not a city search, don't do the city search
            }
            else {*/
                HyperCities.debug(_id + " Looking for " + query.city_name);
                HyperCities.session.set("city", query.city_name.replace(/_/, " "));

                if (_linkUpdateDelay != 0) {
                    setTimeout (zoomToCity, _linkUpdateDelay);
                }
                else {
                    zoomToCity();
                }
            //}
        } // end if a city

        else if (query['item_type'] == 'collection') {
            params.cid = parseInt(query['item_id']);
            //			HyperCities.debug(_id + " Collection id number: " + params.cid);

            // Set option zoom to ture,
            // this method will auto zoom the map to the extent of collection.
            // Because we don't have parentId information,
            // set it to null will disable the delete button in narritive Panel
            setTimeout(function() {
                HyperCities.narrativePanel.load(null, params.cid, {
                    zoom: true
                });
            }, 1000);
        }
        else if (query['item_type'] == 'map' && query['item_id']) {
        // TODO: Map permalinks
        }
        else if (query.item_type == 'snapshot' && query.item_id) {
            HyperCities.debug(_id + "Getting snapshot number " + query.item_id);
            HyperCities.session.loadSnapshot(query.item_id);
        }
        else {
            alert ("Invalid item type.");
        }
    }; // end handlePermalink: function ()

    var _objectPermalinkCallback = function ($data) {
        if ($("Error", $data).length > 0) {
                alert ($("Error > message", $data).text());
                return;
            }
            // zoom to coordinates
            var id = parseInt($("id:first", $data).text());
            /*var center = new GLatLng(parseFloat($("Document > Placemark > LookAt > latitude", $data).text()), parseFloat($("Document > Placemark > LookAt > longitude", $data).text()));
            HyperCities.debug (center);
            if (isNaN(center.lat())) {
                center = new GLatLng(parseFloat($("Document > Placemark > Point > coordinates > latitude", $data).text()), parseFloat($("Document > Placemark > Point > coordinates > longitude", $data).text()));
            };*/
            //var coords = $(" kml > Document > Placemark > Point > coordinates", $data).text();
            //HyperCities.debug("Coords are " + coords);
            //HyperCities.debug($(" kml > Document > Placemark > Point > coordinates", $data).text());
            //var coords = $(" kml > Document > Placemark > Point > coordinates", $data).text().split(',');
            // Zoom to first coordinates because usually, this is close enough to the object
            // TODO: provide more accurate way that accounts for all coordinates
            var coords = $($data).find("default\\:coordinates").text().split(',');
            HyperCities.util.debug("coords" + coords);
            // GMap coordinates are lon, lat rather than lat, lon
            var newCenter = new GLatLng(parseFloat(coords[1]), parseFloat(coords[0]));
            //HyperCities.collectionList.update(newCenter, 14, true);
            HyperCities.mainMap.setCenter(newCenter, 14);

            //HyperCities.debug(HyperCities.mainMap.getCenter());
            // update collection list
            $("#collectionTab").parent().addClass("highlight");
            $("#mapTab").parent().removeClass("highlight");
            $("#intelliList").hide();
            HyperCities.intelliList.reset();
            $("#intelliList").show();
            HyperCities.debug (HyperCities.mainMap.getMapInstance().getBounds());
            HyperCities.collectionList.update(HyperCities.mainMap.getBounds(), HyperCities.mainMap.getZoom(), true);
            
            HyperCities.debug(_id + "Checking collections ...");
            HyperCities.collectionList.openCollection('1');
            $("kml > collections > id", $data).each( function () {
                // open each
                HyperCities.debug(_id + "Opening collection " + $(this).text());
                HyperCities.collectionList.openCollection($(this).text());
            });
            setTimeout ( function () {
                var item = HyperCities.collectionList.addObject(id);
                //HyperCities.debug(item);
                //HyperCities.debug(_id + "Showing info window" );
                //HyperCities.collectionList.showInfoWindow(id);
                HyperCities.mainMap.openHCInfoWindow(item, {maximize: true});
				if ( typeof (item) == 'undefined' ) {
					setTimeout(arguments.callee, 2000);
				}
				else {
					HyperCities.mainMap.openHCInfoWindow(item, {maximize: true});
				}
            },
            3000);
            HyperCities.mainMap.getMapInstance().HCOldLatLng = HyperCities.mainMap.getCenter();
            return;
    } // end _objectPermalinkCallback = function ($data)

    // Public methods
    return {
        permalinkedItems : [],

        /**
         * Initializes the link controller object. This starts the thread listening
         * for updates to the permalinked object.
         */
        /**
         * Initializes the link controller object. This starts the thread listening
         * for updates to the permalinked object.
         */
        init: function() {
            HyperCities.debug(_id + "Starting permalink polling thread.");
            _threadHandle = setInterval (_pollHash, _timingInterval);
            setTimeout (function () {
                _linkUpdateDelay = 0;
            }, 5000);
        },

        updateURL : function ($itemType, $itemId) {
            _lastHash = $itemType + "/" + $itemId;
            window.location.hash = $itemType + "/" + $itemId;
            return;

            if ($itemType == 'snapshots') {
                _lastHash = "snapshots/" + $itemId;
                window.location.hash = "#snapshots/" + $itemId;
            } else {
                _lastHash = "item_type=" + $itemType + "&item_id=" + $itemId;
                window.location.hash = "#item_type=" + $itemType + "&item_id=" + $itemId;
            }
        },

        clearURL : function () {
            _lastHash = "";
            window.location.hash = "#";
            HyperCities.session.permalinkedItems = {
                type: null,
                id: -1,
                bounds: null
            };
        },

        handleZoomLink : function ($zoomLink) {
            var coordinates = _queryParse($zoomLink.substr(1));
            //var lat = parseFloat($hash.substr($hash.indexOf("=") + 1, $hash.indexOf(",") - 1));
            if (coordinates['z'] != undefined) {
                var latlng = coordinates['ll'].split(',');
                if (parseInt(coordinates['z']) == HyperCities.mainMap.getZoom())
                {
                    HyperCities.mainMap.getMapInstance().panTo(new GLatLng(parseFloat(latlng[0]), parseFloat(latlng[1])));
                    HyperCities.debug(_id + "Zoomed to : " + coordinates['ll']);
                }
                else {
                    HyperCities.mainMap.setCenter(new GLatLng(parseFloat(latlng[0]),
                        parseFloat(latlng[1])), parseInt(coordinates['z']));
                    HyperCities.debug(_id + "Zoomed to : " + coordinates['ll'] + " at zoom level " + coordinates['z'] + " Main map zoom: " + HyperCities.mainMap.getZoom());
                }

            //var zoom = parseInt(coordinates[z]);
            // HyperCities.debug(_id + "Zoomed to : " + coordinates['ll'] + " at zoom level " + coordinates['z']);
            //var lng = parseFloat($hash.substr($hash.indexOf(",") + 1, $hash.indexOf("&z") - 1 ));
            //if (zoom == HyperCities.mainMap.getZoom()) HyperCities.mainMap.panTo(new GLatLng(lat, lng));

            } else {

                var lng = parseFloat($hash.substr($hash.indexOf(",") + 1));
                HyperCities.debug($hash.substr($hash.indexOf(",")));
                var zoom = HyperCities.mainMap.getZoom();
                HyperCities.mainMap.panTo(new GLatLng(lat, lng));

            }
            if (coordinates['ts'] != undefined) {
                var timespan = coordinates['ts'].split('-');
                HyperCities.mainMap.setTimespan({
                    min: parseInt(timespan[0]),
                    max: parseInt(timespan[1])
                    }, true);
            }
        },

        getPermalinkBase : function () {
            var locationBar = window.location.toString();
            if (locationBar.indexOf('#') != -1) {
                return locationBar.substr(0, locationBar.indexOf('#'));
            }
            if (locationBar.indexOf('?') != -1) {
                return locationBar.substr(0, locationBar.indexOf('?'));
            }
            else return locationBar;
        },
        /**
         * Generates textual permalinks with links.
         * @param $type     The item type. This should be singular, but will handle plurals and singulars.
         * @param $id       The item's ID number.
         */
        generatePermalink : function ($type, $id) {
            var urlBase = window.location.protocol + "//" + window.location.hostname + window.location.pathname;
            //var locationBar = window.location.toString();
            /*if (locationBar.indexOf('?') != -1) {
                return locationBar.substr(0, locationBar.indexOf('?'));
            }
            if (locationBar.indexOf('#') != -1) return locationBar.substr(0, locationBar.indexOf('#'));*/
            if ($type.substring($type.length - 1) != 's') $type += 's';
            return '<a href="'  + urlBase + '#' + $type + '/' + $id +'" id="objectPermalink">'
            + urlBase + '#' + $type + '/' + $id + '</a>';
//            return '<a href="'  + urlBase + '#item_type=' + $type + '&item_id=' + $id +'" id="objectPermalink">'
//            + urlBase + '#item_type=' + $type + '&amp;item_id=' + $id + '</a>';
        }
    }
}();
