// vim: sw=4:ts=4:nu:nospell

/**
 * HyperCities narrativePanel Object
 *
 * @author    Chen-Kuei Lee
 * @copyright (c) 2008, by HyperCities Tech Team
 * @date      2009-07-20
 * @version   $Id$
 *
 */


HyperCities.narrativePanel = function() {
    // do NOT access javascript generated DOM from here; elements don't exist yet

    // Private variable goes here
    var _id        = "[HyperCities.narrativePanel] ",

    // Map Related Variables
    _mapBounds  = null,
    _mapZoom    = null,
    _HMarker    = null,

    // Timespan Related Variables
    _timespanStack  = [],

    // narrativePanel Related Variables
    _objects       = [], // Objects that add By Narrative Panel
    _panelSet      = [], // Set of Panel Container
    _parentId      = null,
    _progressCount = 0,

    // intelliList Related Variables
    _initialized   = false,
    _originalMode  = HyperCities.config.MODE_DEFAULT,
    _zoomToExtent  = false,
	_sidebarWidth  = 0,

    // Narrative Options Variables
    _isSyncMap     = false,
    _isListView    = false,
    _isDateView    = true,

    // Citations
    _citations = [],

    // The ID number of the narrative's map, if any.
    _baseMap = null,

    // CSS classes constant used by narrativePanel
    CLASSES = {
        panel: "HCNarrativePanel",
        panelInfo: "HCNarrativePanelInfo",
        panelList: "HCNarrativePanelList",
        panelItem: "HCNarrativePanelItem",
        loading: "loading",
        closeBtn: "closeBtn",
        deleteBtn: "deleteBtn",
        gripBtn: "gripBtn",
        centerBtn: "centerBtn",
        expandBtn: "expandBtn",
		backBtn: "backBtn",
        listView: "listView",
        title: "title",
		author: "author",
        metadata: "HCNarrativeMetadata",
        toolbar: "toolbar",
        toolPanel: "toolPanel",
        toolPanelContent: "toolPanelContent",
        extDate: "extDate",
        content: "HCNarrativeContent",
        description: "description",
        blankLink: "blankLink",
        citationLink: "citationLink",
        snapshotLink: "snapshotLink",
        editLink: "editLink",
        deleteLink: "deleteLink",
        optionLink: "optionLink",
        options: "optionList",
        syncMapOn: "syncMapOn",
        syncMapOff: "syncMapOff",
        showExpanded: "showExpanded",
        showList: "showList",
        showDate: "showDate",
        showDatetime: "showDatetime",
        autoZoomOn: "autoZoomOn",
        autoZoomOff: "autoZoomOff",
        permaLink: "permaLink",
        permaLinkUrl: "permaLinkUrl",
        link: "link",
        selected: "selected",
        item: "item"
    };

    var _initMarker = function() {

        var markerOptions, icon = new GIcon(G_DEFAULT_ICON, "images/markerHighlight.png");

        icon.iconSize   = new GSize(78, 76);
        icon.imageMap   = [0, 0, 76, 0, 76, 76, 0, 76];
        icon.iconAnchor = new GPoint(39, 38);

        markerOptions = {
            icon : icon,
            clickable : false,
            hide: true
        };

        _HMarker = new GMarker(new GLatLng(0, 0), markerOptions);
        _HMarker.importance = 10;

        HyperCities.mainMap.addOverlay(_HMarker);
    };

    /**
	 * Given object id, find the index of object in _objects array
	 * @param integer $id
	 * @return integer The index of $linkId in _objects array, or -1 if not found
	 */
    var _getObjectIndexById = function($id) {
        var index;

        index = _objects.length;
        while ( index-- > 0 ) {
            if ( _objects[index].id === $id )
                return index;
        }

        return -1;
    };

    var _createPanelDom = function () {

        var panelId       = _panelSet.length + 1,
        panelWidth    = $("#narrativePanelWrapper").width(),
        panelOffset   = 0,
        panelDom      = $(document.createElement("div")),
        panelInfo     = $(document.createElement("div")),
        panelList     = $(document.createElement("div")),
        panelInfoHtml = ['<div class="', CLASSES.closeBtn, '"></div>',
        '<div class="', CLASSES.backBtn, '" title="Back to previous collection"><</div>',
        '<div class="', CLASSES.loading, '"> Loading... </div>',
        '<div class="', CLASSES.toolbar, '">',
        '<span class="', CLASSES.optionLink, '">Options</span> | ',
        '<span class="', CLASSES.permaLink, '">Link</span>', '</div>',
        '<div class="', CLASSES.toolPanel, '">',
        '<div class="', CLASSES.closeBtn, '"></div>',
        '<div class="', CLASSES.toolPanelContent, '"></div></div>'],
        loadingHtml   = ['<div class="', CLASSES.loading, '"> Loading... </div>'];

        if ( panelId > 1 ) {
            panelOffset = panelWidth;
        }

		// If is First Level, remove back button
		if ( panelId == 1 ) {
			panelInfoHtml.splice(3,3);
		}

        panelInfo.attr("id", "panelInfo_" + panelId)
        .addClass(CLASSES.panelInfo)
        .html(panelInfoHtml.join (''));

        panelList.attr("id", "panelList_" + panelId)
        .addClass(CLASSES.panelList)
        .html(loadingHtml.join (''));

        panelDom.attr("id", "panel_" + panelId)
        .data("id", panelId)
        .addClass(CLASSES.panel)
        .css("left", panelOffset)
        .css("width", panelWidth - 10)
        .append(panelInfo)
        .append(panelList)
        .bind('click', _panelClickHandler); // Bind Narrative Panel Click Event

        return panelDom;
    };

    /**
	 * Create Dom Node of New Narrative Panel, and shift original one to left
	 */
    var _appendPanel = function($collectionId) {

        var panelDom   = _createPanelDom(),
        panelWidth = $("#narrativePanelWrapper").width();

        $("#narrativePanelWrapper").append(panelDom);

        // Swap the Panel
        $("#narrativePanelWrapper ." + CLASSES.panel)
        .animate({
            "left": "-=" + panelWidth + "px"
            }, "slow");

    };

    /**
	 * Setup the Dom Node of Narrative Panel
	 */
    var _initNarrative = function () {

        var panelDom, children, totalChildren,
			panelWidth = parseInt($(window).width()/3.0);

        // Initial private variables
        _mapBounds = HyperCities.mainMap.getBounds();
        _mapZoom   = HyperCities.mainMap.getZoom();
        _timespanStack  = [];
        _panelSet       = [];
        _progressCount  = 0;
		_sidebarWidth   = $('#sidebarWrapper').width();

		$("#narrativePanelWrapper").css("width", panelWidth);
        panelDom = _createPanelDom();

        if ( !_initialized ) {
            $("#narrativePanelWrapper").append(panelDom).fadeIn();

            // Change sidebar Style
            $("#sidebarWrapper").css("background-color", "#8d8d8d")
								.css("width", panelWidth);

            $("#sidebarWrapper .ui-resizable-handle").css("background-color", "#AFAFAF");

            // Setup Highlight Marker
            _initMarker();
            _objects = [];
        }
        else {
            // Remove All marker Created in panel
            children = $.map($("#narrativePanelWrapper ." + CLASSES.panelItem), function($node){
                return $($node).data("id");
            });
            totalChildren = children.length;
            // remove each child by yielding processes
            if ( totalChildren > 0 ) {
                setTimeout(function() {
                    var childId = children.shift();

                    _removeMarker(childId);

                    if ( children.length > 0 ) {
                        setTimeout(arguments.callee, 10);
                    }
                }, 10);
            }

            $("#narrativePanelWrapper").fadeOut().empty().append(panelDom).fadeIn();
        }
		
        // Disable auto map refresh in narrative mode
        HyperCities.mainMap.enableSync(false);
		HyperCities.adjustLayout({sync: false});

        _initialized = true;
    };

    var _resetNarrative = function () {

        if ( _HMarker instanceof GMarker ) {
            HyperCities.mainMap.removeOverlay(_HMarker);
        }

        // Clean up variables
        // Note: don't reset _objects here, we need to use _objects array to remove marker overlay
        //       _objects will be reset when next time narrative panel is initialized
        _mapBounds = null;
        _mapZoom   = null;
        _HMarker   = null;
        _initialized  = false;
        _zoomToExtent = false;
        _isListView   = false,
        _isDateView   = true,
        _timespanStack = [];
        _panelSet      = [];
		_citations     = [];
        _parentId      = null;
        _progressCount = 0;

        // Enable auto map refresh in narrative mode
        HyperCities.mainMap.enableSync(true);

        // Hide Narrative Panel
        $("#narrativePanelWrapper").fadeOut().empty().css("width", _sidebarWidth);

        // Restore sidebar Style
        $("#sidebarWrapper").css("background-color", "#232323")
							.css("width", _sidebarWidth);
        $("#sidebarWrapper .ui-resizable-handle").css("background-color", "#232323");

        // Restore Session Mode Variable
        HyperCities.session.set("mode", _originalMode);
		HyperCities.adjustLayout({sync: false});
    };

    /**
	 * Event Delegation Handler to process all click event on narrative panel
	 * @param Event $event
	 * @return boolean always return false to prevent event propagation
	 */
    var _panelClickHandler = function ($event) {

        var target = $($event.target);
        
        if ( target.hasClass(CLASSES.blankLink) ) { // Bypass the image link click event
            return;
        }
        else if ( target.parent().hasClass (CLASSES.citationLink)) {
            _citationClickHandler($event);
        }
        else if (target.hasClass (CLASSES.snapshotLink)) {
            _snapshotClickHandler ($event);
        }
        else if ( target.hasClass(CLASSES.closeBtn) ) { // user click on Close Button
            _closeBtnClickHandler($event);
        }
        else if ( target.hasClass(CLASSES.centerBtn) ) { // user click on Center Item Button
            _centerItem($event);
        }
        else if ( target.hasClass(CLASSES.expandBtn) ) { // user click on Expand Collection Button
            _expandCollection($event);
        }
		else if ( target.hasClass(CLASSES.backBtn) ) { // user click on Back Prev Collection Button
			_closeNarrative($event);
		}
        else if ( target.hasClass(CLASSES.deleteBtn) || target.hasClass(CLASSES.deleteLink) ) { // user click on Delete Item Button
            _deleteBtnClickHandler($event);
        }
        else if ( target.hasClass(CLASSES.permaLinkUrl) ) { // user click on permaLinkUrl Box
            target.select();
        }
        else if ( target.hasClass(CLASSES.optionLink) ) { // user click on option Link
            _openOptionToolPanel($event);
        }
        else if ( target.hasClass(CLASSES.permaLink) ) { // user click on permaLink Link
            _openLinkToolPanel($event);
        }
        else if ( target.parent().hasClass(CLASSES.toolPanelContent) ) { // user click on options choice link
            _optionsClickHandler($event);
        }
        else if ( target.hasClass(CLASSES.editLink) ) {
            _updateCollection($event);
        }
        else {
            HyperCities.util.debug(_id + "[A2] Click Narrative Panel");
            HyperCities.util.debug(target);
        }

        return false;
    };

    var _closeBtnClickHandler = function($event) {

        var target = $($event.target);

        if ( target.parent().hasClass(CLASSES.toolPanel) ) { // It's toolPanel's Close Button
            _closeToolPanel($event);
        }
        else { // Otherwise, it's Main Panel's Close Button
            if ( confirm ("Do you want to close the collection and enter the general Hypercities environment?\n\nIf so, you can click the back button to return to the current collection."))
                _closeAllNarrative($event);
        }

        

        return false;
    };

    var _deleteBtnClickHandler = function($event) {

        var target       = $($event.target),
        panelId      = _panelSet.length + 1,
        hasPermision = (HyperCities.user.isLogin() === true),
        isDeleteLink = target.hasClass(CLASSES.deleteLink),
        isCollection = target.prev().hasClass(CLASSES.expandBtn),
        itemId       = target.parent().data("id"),
        itemTitle    = target.next().next().text(),
        parentDom    = $("#panelInfo_" + panelId),
        parentId	 = parentDom.data("id"),
        response     = false;

        if ( !hasPermision ) {
            return false;
        }

        if ( isDeleteLink || isCollection ) {
            if ( isDeleteLink ) { // Get Collection Info
                itemTitle = parentDom.find(" ." + CLASSES.title).text();
                itemId    = parentDom.data("id");
                parentId  = parentDom.data("parentId");
            }

            //			HyperCities.util.debug(_id + "[A2] Delete Collection " + itemId + " in collection " + parentId);
            response = window.confirm("Are you sure you want to delete collection " + itemTitle + "?");
            if ( !response ) {
                return false;
            }

            // Call Delete Collection Function
            var params = {
                objectId: itemId,
                parentId: parentId
            };
            $.post("./deleteCollection.php", params, function($response){
                var success = $($response).find("Success > Message").text();
                var error   = $($response).find("Error > Message").text();

                if ( error.length > 0 ) {
                    alert(error);
                }
                else {
                    // Fade out deleted item
                    // alert(success);
                    $("#narrativePanelWrapper ." + CLASSES.panelItem + itemId).fadeOut();
                    if ( isDeleteLink ) {
                        _closeNarrative();
                    }
                }

            }, "xml");
        }
        else {
            //			HyperCities.util.debug(_id + "[A2] Delete Item " + itemId + " in collection " + parentId);
            response = window.confirm("Are you sure you want to delete item " + itemTitle + "?");
            if ( !response ) {
                return false;
            }

            // Call Delete Object Function
            var params = {
                objectId: itemId,
                parentId: parentId
            };
            $.post("./deleteObject.php", params, function($response){
                var success = $($response).find("Success > Message").text();
                var error   = $($response).find("Error > Message").text();

                if ( error.length > 0 ) {
                    alert(error);
                }
                else {
                    // Fade out deleted item
                    // alert(success);
                    $("#narrativePanelWrapper ." + CLASSES.panelItem + itemId).fadeOut();
                }

            }, "xml");
        }

        return false;
    };

    var _optionsClickHandler = function($event) {

        var target = $($event.target),
        items;

        if ( target.hasClass(CLASSES.syncMapOn) && _isSyncMap == false ) {
            HyperCities.util.debug("SyncMap On");

            _isSyncMap = true;
            $("#narrativePanelWrapper ."+CLASSES.syncMapOn).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.syncMapOff).removeClass(CLASSES.selected).addClass(CLASSES.link);
        }
        else if ( target.hasClass(CLASSES.syncMapOff) && _isSyncMap == true ) {
            HyperCities.util.debug("SyncMap Off");

            _isSyncMap = false;
            $("#narrativePanelWrapper ."+CLASSES.syncMapOff).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.syncMapOn).removeClass(CLASSES.selected).addClass(CLASSES.link);
        }
        else if ( target.hasClass(CLASSES.showExpanded) && _isListView == true ) {
            HyperCities.util.debug("Expanede View");

            _isListView = false;
            $("#narrativePanelWrapper ."+CLASSES.showExpanded).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.showList).removeClass(CLASSES.selected).addClass(CLASSES.link);
            items = $("#narrativePanelWrapper ."+CLASSES.panelItem);
            items.removeClass(CLASSES.listView)
            .find("."+CLASSES.metadata).show().end()
            .find("."+CLASSES.content).show().end()
            .find("."+CLASSES.gripBtn).hide().end()
            .find("."+CLASSES.deleteBtn).hide();

            $("#narrativePanelWrapper ." + CLASSES.panelList).jScrollPane().sortable('disable');
        }
        else if ( target.hasClass(CLASSES.showList) && _isListView == false ) {
            HyperCities.util.debug("List View");

            _isListView = true;
            $("#narrativePanelWrapper ."+CLASSES.showList).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.showExpanded).removeClass(CLASSES.selected).addClass(CLASSES.link);
            items = $("#narrativePanelWrapper ."+CLASSES.panelItem);
            items.addClass(CLASSES.listView)
            .find("."+CLASSES.metadata).hide().end()
            .find("."+CLASSES.content).hide().end()
            .find("."+CLASSES.gripBtn).show().end()
            .find("."+CLASSES.deleteBtn).show();

            $("#narrativePanelWrapper ." + CLASSES.panelList).jScrollPane().sortable('enable');
        }
        else if ( target.hasClass(CLASSES.showDate) && _isDateView == false ) {
            HyperCities.util.debug("Show Date");

            // Change Link Style
            _isDateView = true;
            $("#narrativePanelWrapper ."+CLASSES.showDate).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.showDatetime).removeClass(CLASSES.selected).addClass(CLASSES.link);
            $("#narrativePanelWrapper ."+CLASSES.extDate).hide();
        }
        else if ( target.hasClass(CLASSES.showDatetime) && _isDateView == true ) {
            HyperCities.util.debug("Show Date Time");

            _isDateView = false;
            $("#narrativePanelWrapper ."+CLASSES.showDatetime).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.showDate).removeClass(CLASSES.selected).addClass(CLASSES.link);
            $("#narrativePanelWrapper ."+CLASSES.extDate).show();
        }
        else if ( target.hasClass(CLASSES.autoZoomOn) && _zoomToExtent == false ) {
            HyperCities.util.debug("Auto ZoomIn On");

            _zoomToExtent = true;
            $("#narrativePanelWrapper ."+CLASSES.autoZoomOn).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.autoZoomOff).removeClass(CLASSES.selected).addClass(CLASSES.link);
        }
        else if ( target.hasClass(CLASSES.autoZoomOff) && _zoomToExtent == true ) {
            HyperCities.util.debug("Auto ZoomIn Off");

            _zoomToExtent = false;
            $("#narrativePanelWrapper ."+CLASSES.autoZoomOff).removeClass(CLASSES.link).addClass(CLASSES.selected);
            $("#narrativePanelWrapper ."+CLASSES.autoZoomOn).removeClass(CLASSES.selected).addClass(CLASSES.link);
        }
    };

	var _closeAllNarrative = function($event) {

		var timeStack = _timespanStack[_timespanStack.length-1],
			children  = [],
			totalChildren = 0;

		HyperCities.util.debug(_id + "[A2] Close All Narrative Panel ");

		// Remove All marker Created in Narrative View
        children = $.map($("#narrativePanelWrapper" + " ." + CLASSES.panelItem), function($node){
            return $($node).data("id");
        });
        totalChildren = children.length;

        // remove each child by yielding processes
        if ( totalChildren > 0 ) {
            setTimeout(function() {
                var childId = children.shift();

                _removeMarker(childId);

                if ( children.length > 0 ) {
                    setTimeout(arguments.callee, 10);
                }
            }, 10);
        }

        //remove base map, if there is one
        HyperCities.session.set("baseMap", null);

		_resetNarrative();
        HyperCities.linkController.clearURL();

        // Switch to privious Timespan
        if ( typeof(timeStack) !== 'undefined' ) {
            HyperCities.timebar.setTime(timeStack.timebar.currentYear, timeStack.timebar.startYear, timeStack.timebar.endYear, timeStack.timebar.activeYear, true);
		}
	};

    var _citationClickHandler = function ($event) {
        var refCode = $($event.target).parent().get(0).id.toString().split('_');
        var title = $($event.target).text();
        HyperCities.mainMap.showCitation(refCode[0], refCode[1], title, _citations[refCode[0]][refCode[1]]);
    };

    var _snapshotClickHandler = function ($event) {
        var snapshotBase = $($event.target);
        if (snapshotBase.hasClass("activeSnapshot")) {
            HyperCities.util.debug (_id + "Rolling back snapshot");
            HyperCities.session.rollbackSnapshot();
            snapshotBase.find("img:first").attr('src', './images/thumb-n.gif');
            snapshotBase.removeClass("activeSnapshot");
        } else {
            var oldSnapshot = $("a.snapshot.activeSnapshot");
            if (oldSnapshot.length > 0) {
                oldSnapshot.find("img:first").attr('src', './images/thumb-n.gif');
                oldSnapshot.removeClass("activeSnapshot");
                HyperCities.session.rollbackSnapshot();
            }
            var snapshotId = $($event.target).attr('snapshotid');
            $("a.activeSnapshot").removeClass("activeSnapshot");
            snapshotBase.addClass ("activeSnapshot");
            $($event.target).find("img:first").attr('src', "./images/tipRight.gif");
            HyperCities.util.debug (_id + "Loading snapshot " + snapshotId);
            HyperCities.session.loadSnapshot(snapshotId);
        }
        return false;
    }

    var _closeNarrative = function($event) {

        var panelId    = _panelSet.length + 1,
        panelWidth = $("#narrativePanelWrapper").width(),
        timeStack  = _timespanStack.pop(),
        children   = [],
        totalChildren = 0;

        HyperCities.util.debug(_id + "[A2] Close Narrative Panel " + panelId);

        // Remove All marker Created in this panel
        children = $.map($("#panel_" + panelId + " ." + CLASSES.panelItem), function($node){
            return $($node).data("id");
        });
        totalChildren = children.length;
        // remove each child by yielding processes
        if ( totalChildren > 0 ) {
            setTimeout(function() {
                var childId = children.shift();

                _removeMarker(childId);

                if ( children.length > 0 ) {
                    setTimeout(arguments.callee, 10);
                }
            }, 10);
        }

        //remove base map, if there is one
        //if (_baseMap != null) HyperCities.mapList.removeMap(_baseMap);
        var baseMap = $("#panelInfo_" + panelId).data("baseMap");
        if (baseMap != null && baseMap != '' && $("#panelInfo_" + panelId - 1).data("baseMap") != baseMap
            && $("#panelInfo_" + panelId - 2).data("baseMap") != baseMap) HyperCities.mapList.removeMap(baseMap);
        HyperCities.session.set("baseMap", null);

        if ( panelId == 1 ) { // only one panel left, close narrative view
            _resetNarrative();
        }
        else { // roll back to previous panel
			
            // Close All tool panel
            _closeToolPanel();

            // Swap the Panel
            $("#narrativePanelWrapper ." + CLASSES.panel)
            .animate({
                "left": "+=" + panelWidth + "px"
                }, "slow", "linear",
            function(){
                $("#panel_" + panelId).remove();
            }
            );

            // Zoom to previous collection extent if _zoomToExtent is true
            if ( _zoomToExtent ) {
                _zoomToCollection($("#panelInfo_" + (panelId - 1)).data("bBox"));
            }

            _panelSet.pop();
            _parentId = $("#panelInfo_" + (panelId - 1)).data("parentId");
        }

        // Switch to privious Timespan
        if ( typeof(timeStack) !== 'undefined' ) {
            HyperCities.timebar.setTime(timeStack.timebar.currentYear, timeStack.timebar.startYear, timeStack.timebar.endYear, timeStack.timebar.activeYear, true);

        //HyperCities.mainMap.setTimespan({min: timeStack.mapTime.min, max: timeStack.mapTime.max}, true);
        }

    };

    var _centerItem = function($event) {

        var itemDom   = $($event.target).parent(),
        itemId    = itemDom.data("id"),
        itemIndex = _getObjectIndexById(itemId),
        item;

        $($event.target).blur();

        //		HyperCities.util.debug(_id + "[A2] Center to Item " + itemId);
        if ( itemIndex >= 0 ) {
            item = _objects[itemIndex];

            // Make sure we have the information of object
            if ( typeof(item) !== 'undefined' ) {
                if ( item.hidden ) { // item is overlaid by collectionList
                    HyperCities.collectionList.panToItem(itemId, {
                        openWindow: false
                    });
                }
                else {
                    HyperCities.narrativePanel.panToItem(itemId, {
                        openWindow: false
                    });
                }
            }
        }
    };

	var _updateCollection = function($event) {

		var panelId    = _panelSet.length + 1,
			itemDom    = $("#panelInfo_" + panelId),
			itemId     = itemDom.data("id"),
			itemTitle  = itemDom.find("." + CLASSES.title).text(),
			itemAuthor = itemDom.find("." + CLASSES.author).text(),
			itemDesc   = itemDom.find("." + CLASSES.description).text(),
			ownerId    = itemDom.data("ownerId"),
			stateId    = itemDom.data("stateId");


//		HyperCities.debug(_id + "[A2] Collection ID " + itemId);
//		HyperCities.debug(_id + "[A2] Collection Title " + itemTitle);
//		HyperCities.debug(_id + "[A2] Collection Author " + itemAuthor);
//		HyperCities.debug(_id + "[A2] Collection Desc " + itemDesc);
//		HyperCities.debug(_id + "[A2] Collection Owner " + ownerId);

		HyperCities.collectionList.updateCollection({
			id: itemId,
			title: itemTitle,
			author: itemAuthor,
			description: itemDesc,
			ownerId: ownerId,
			stateId: stateId
		});
	};

    var _expandCollection = function($event) {

        var panelId      = _panelSet.length + 1,
        itemDom      = $($event.target).parent(),
        itemId       = itemDom.data("id"),
        collectionId = $("#panelInfo_" + panelId).data("id"),
        params       = {
            func : "narrativePanel.getNarrative",
            cid : itemId
        };

        $($event.target).blur();

        //		HyperCities.util.debug(_id + "[A2] Expand to Collection " + itemId);
        _panelSet.push({
            parentId: collectionId,
            collectionId: itemId
        });
        _parentId = collectionId;

        _appendPanel(itemId);

        // Query Narrative Content
        $.post("./getNarrative.php", params, _updateNarrative, "xml");
    };

    var _zoomToCollection = function ($bBox) {

        var temp1, temp2, offsetX, offsetY, newBound, newZoom,
        bBox = $bBox;
        /*
		// Apply the offset to get actual bound in View (Extend the Bound)
		temp1 = HyperCities.mainMap.fromContainerPixelToLatLng(new GPoint(100,100));
		temp2 = HyperCities.mainMap.fromContainerPixelToLatLng(new GPoint(140,180));

		offsetX = Math.abs(temp1.x - temp2.x);
		offsetY = Math.abs(temp1.y - temp2.y);
		bBox.north = bBox.north + ( offsetX );
		bBox.east  = bBox.east + ( offsetY / 4 );
		bBox.south = bBox.south - ( offsetX * 1.5);
		bBox.west  = bBox.west - ( offsetY );
*/
        // Calculate the actual bound
        newBound = new GLatLngBounds();

        newBound.extend(new GLatLng(bBox.north, bBox.east));
        newBound.extend(new GLatLng(bBox.south, bBox.west));

        // Get max zoomlevel that fit bound, and recenter the map
        newZoom = HyperCities.mainMap.getBoundsZoomLevel(newBound);
        if ( newZoom > 0 ) {
            newZoom--;
        }
        HyperCities.mainMap.setCenter(newBound.getCenter(), newZoom);

    };

    var _parseBoundingBox = function ($bBoxString) {

        var pattern = /^BBox=\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\]/i,
        bBoxArray = pattern.exec($bBoxString),
        bBox = {};

        if ( bBoxArray === null) {
            return null;
        }
        else {
            bBox.west  = parseFloat(bBoxArray[1]);
            bBox.south = parseFloat(bBoxArray[2]);
            bBox.east  = parseFloat(bBoxArray[3]);
            bBox.north = parseFloat(bBoxArray[4]);
        }

        return bBox;
    };

    var _parseTimePrimitive = function($timeStr) {
        //		HyperCities.util.debug(_id + "[A2] Parse time primitive " + $timeStr);

        var timeString;

        if ( $timeStr[0] == '-' ) { // BCE Date
            timeString = $timeStr.substr(0,20);
        }
        else { // CE Date
            timeString = $timeStr.substr(0,19);
        }
		
        //		HyperCities.util.debug(_id + "[A2] Parse time primitive " + timeString);
        return Date.parse(timeString);
    };

    var _formatTime = function($begin, $end, $when) {

        var	yearStr = "",
        timeStr = "",
        timeArray = [],
        timeStyle = 'style="display: inline;"';

        if ( _isDateView ) {
            timeStyle = "";
        }

        if ( $when.length > 0 ) {
            if ( $when[0] == '-' ) {
                timeStr = "BCE ";
                $when = $when.substr(1,19);
            }
            yearStr = Date.parse($when).getFullYear();
            timeArray = [ yearStr, $when.substr(4,6),
            '<span class="', CLASSES.extDate, '" ', timeStyle, '>', $when.substr(11,8), '</span>'];

            return timeStr + timeArray.join('');
        }

        if ( $begin.length > 0 ) {
            if ( $begin[0] == '-' ) { // BCE Date
                timeStr = "BCE ";
                $begin = $begin.substr(1,19);
            }
            yearStr = Date.parse($begin).getFullYear();
            timeArray = [ yearStr, $begin.substr(4,6),
            '<span class="', CLASSES.extDate, '" ', timeStyle, '>', $begin.substr(11,8), '</span>'];

            timeStr += timeArray.join('');
        }

        timeStr+= " - ";

        if ( $end.length > 0 ) {
            if ( $end[0] == '-' ) { // BCE Date
                timeStr += "BCE ";
                $end = $end.substr(1,19);
            }
            yearStr = Date.parse($end).getFullYear();
            timeArray = [ yearStr, $end.substr(4,6),
            '<span class="', CLASSES.extDate, '" ', timeStyle, '>', $end.substr(11,8), '</span>'];

            timeStr += timeArray.join('');
        }

        return timeStr;
    };

    var _addMarker = function ($itemId, $itemName, $itemUrl, $itemKml, $overlay, $dateFrom, $dateTo) {

        // Create Overlay for the Item
        var panelId       = _panelSet.length + 1,
        markerOverlay = new GHCMarker(HyperCities.mainMap.getMapInstance(), $itemKml);

        // Add Item to _objects Array
        var markerObject = {
            type : CLASSES.item,
            id   : $itemId,
            name : $itemName,
            url  : $itemUrl,
            kml  : $itemKml,
            dateFrom : $dateFrom,
            dateTo   : $dateTo,
            overlay  : markerOverlay,
            panelId  : panelId,
            added    : true,
            hidden   : $overlay
        };

        if ( _getObjectIndexById($itemId) < 0 ) {
            _objects.push(markerObject);
            // Overlay marker if it's not yet on the map
            if (!$overlay) {
                setTimeout(function () {HyperCities.mainMap.addOverlay(markerObject.overlay);}, 1500);
                
            }
        }
    };

    var _removeMarker = function ($itemId) {

        var itemIndex = _getObjectIndexById($itemId),
        item;

        //		HyperCities.util.debug(_id + "[A2] Remove Marker " + $itemId);
        if ( itemIndex >= 0 ) {
            item = (_objects.splice(itemIndex, 1))[0];

            if ( item.overlay instanceof GOverlay ) {
                HyperCities.mainMap.removeOverlay(item.overlay);
            }
        }
    };

    var _extractCitations = function ($itemId, $citationData) {
        _citations[$itemId] = [];
        $("citation", $citationData).each(function () {

            _citations[$itemId][$(this).attr("ref")] = $(this).text();
            //if (typeof(this.innerHTML) == 'undefined') _citations[$itemId][$(this).attr("ref")] = $(this).text();
            //else _citations[$itemId][$(this).attr("ref")] = $(this).html();
        });
    }

    var _appendNarrativeItem = function ($itemXml, $openedList, $checkedList, $isCollectionOwner) {

        var panelId       = _panelSet.length + 1,
        isNetworkLink = ( $itemXml.nodeName == "NetworkLink" ),
        isPlacemark   = ( $itemXml.nodeName == "Placemark" ),
        itemDom       = null,
        itemXml       = $($itemXml),
        itemId        = itemXml.attr("id");
        itemName      = itemXml.find("name:first").text(),
        itemUrl       = itemXml.find("[nodeName=atom:link]:first").attr("href"),
        creator       = itemXml.find("[nodeName=atom:name]:first").text(),
        description   = itemXml.find("description > ExtendedData > content").text(),
        timeStamp     = itemXml.find("TimeStamp:first"),
        timeSpan      = itemXml.find("TimeSpan:first"),
        timeBegin     = timeSpan.find("begin").text(),
        timeEnd       = timeSpan.find("end").text(),
        timeWhen      = timeStamp.find("when").text(),
        isExternal    = parseInt(itemXml.find("ExtendedData:last > [nodeName=hc:external]").text()),
        itemOrderId   = parseInt(itemXml.find("ExtendedData:last > [nodeName=hc:orderId]").text()),
        itemOrder     = parseInt(itemXml.find("ExtendedData:last > [nodeName=hc:order]").text()),
        ownerId       = parseInt(itemXml.find("ExtendedData:last > [nodeName=hc:ownerId]").text()),
        stateId       = parseInt(itemXml.find("ExtendedData:last > [nodeName=hc:stateId]").text()),
        isChecked     = ($.inArray(itemId, $checkedList) >= 0),
        isOpened      = ($.inArray(itemId, $openedList) >= 0),
        isEditable    = ($isCollectionOwner || HyperCities.user.hasUpdatePrivilege(itemId, ownerId, stateId)),
		isDeletable   = ($isCollectionOwner || HyperCities.user.hasDeletePrivilege(itemId, ownerId, stateId)),
        itemStyle     = 'style="display: block;"',
        dateFrom      = null,
        dateTo        = null,
        domHtml       = [],
        totalItems    = 0;

        _extractCitations(itemId, itemXml.find("citationlist"));

        if ( _isListView ) {
            itemStyle = '';
        }

        if ( timeSpan.length > 0 ) { // It's time span
            dateFrom = _parseTimePrimitive(timeBegin);
            dateTo   = _parseTimePrimitive(timeEnd);
        }
        // otherwise look for stamp
        else if ( timeStamp.length > 0 ) {
            dateFrom = _parseTimePrimitive(timeWhen);
            if (dateFrom == null) dateTo = null;
            else dateTo   = dateFrom.clone();
        }

        // Set Collection Metadata
        domHtml = [ '<div class="', CLASSES.panelItem, ' ', CLASSES.panelItem, itemId, '" id="',
        CLASSES.panelItem, "_", panelId, "_", itemId, '">',
        '<div class="', CLASSES.centerBtn, '" title="Center to ', itemName ,'"></div>',
        '<div class="', CLASSES.deleteBtn, '"></div>',
        '<div class="', CLASSES.gripBtn, '"></div>',
        '<div class="', CLASSES.title, '" title="', itemName, '">', itemName, '</div>',
        '<div class="', CLASSES.metadata, '" ', itemStyle, '>',
        _formatTime(timeBegin, timeEnd, timeWhen), '<br/>',
        'Creator : ', creator, '</div>',
        '<div class="', CLASSES.content, '" ', itemStyle, '>', description, '</div></div>'];

        if ( isExternal ) {
        //			HyperCities.util.debug(_id + "[A2] Append External Kml " + itemId);
        }
        else if ( isNetworkLink ) {
            //			HyperCities.util.debug(_id + "[A2] Append Network Link " + itemId);
            domHtml[13] = CLASSES.expandBtn;
			domHtml[14] = '" title="Open collection ';
			domHtml[16] = '">></div>';
        }
        else if ( isPlacemark ) {
            //			HyperCities.util.debug(_id + "[A2] Append Placemark " + itemId);
            domHtml[37] = "Author : ";


            // Add Marker to Map
            _addMarker(itemId, itemName, itemUrl, $itemXml, isChecked, dateFrom, dateTo);
        }

        // Disable edit function if user does not have permision
		if (!isEditable) {
			domHtml.splice(20, 3);
		}

        if (!isDeletable) {
            domHtml.splice(17, 3);
        }

        itemDom = $(domHtml.join(''));
        itemDom
        .data("id", itemId)
        .data("orderId", itemOrderId)
        .data("order", itemOrder)
        .hover( function () {
            HyperCities.narrativePanel.highlightItem(itemId);
        },
        function () {
            HyperCities.narrativePanel.unHighlightItem(itemId);
        });

        if ( _isListView ) {
            itemDom.addClass(CLASSES.listView);
        }

        // Handle MediaObject
        itemDom.find("img.Itemshockwave").replaceWith('<object></object>','shockwave');
        itemDom.find("img.Itemaudio").replaceWith('<object></object>','audio');
        itemDom.find("object").prepend('<param name="wmode"	value="transparent"/>');
        itemDom.find("object embed").each( function () {
            var target = $(this);
            target.attr('wmode', 'transparent');
        });

        // Handle Href (open in new window)
        itemDom.find("."+CLASSES.content+" a").each(function () {
            if ($(this).hasClass(CLASSES.citationLink)) {
                $(this).wrap(document.createElement("sup"));
            }
            else if ($(this).hasClass(CLASSES.snapshotLink)) {
                $(this).prepend('<img src="./images/thumb-n.gif" width="10px" height="10px" />');
            }
            else {
                $(this).attr('target','_blank').addClass(CLASSES.blankLink);
            }
        })
        

        var ImageSubId = 0;
        var ImagePanelObject = {
            id: itemId,
            title: itemName
        };

        itemDom.find("."+CLASSES.content+" img")
        .css("border", "1px solid #666666")
        .addClass(CLASSES.blankLink)
        .each(function() {
            var imageId = ImagePanelObject.id + "_" + ImageSubId++;

            var imageObject = {
                id: imageId,
                title: ImagePanelObject.title,
                sourceURL: $(this).attr("src"),
                height: 200,
                width: 320
            };

            var image = new Image();
            image.onload = function () {
                imageObject.height = this.height;
                imageObject.width  = this.width;
            };
            image.src = $(this).attr("src");

			var anchorNode = $(this).parent().get(0);

			if ( anchorNode.nodeName === "A" && anchorNode.href !== "" ) {
				$(this).css("border", "0px");
				return;
            } else {
                $(this).css("cursor", "pointer")
                .click(HyperCities.mainMap.overlayImageBox(imageObject));
            }
        });

        $("#panelList_" + panelId)
        .find("." + CLASSES.loading)
        .remove().end()
        .append(itemDom);

        // only update jScrollpane Once, when last item loaded
        if ( _progressCount == 0 ) {

            totalItems = $("#panelList_" + panelId + " ." + CLASSES.panelItem).length;

            if ( totalItems > 1 && isEditable ) {
                // since all item were loaded, make Items sortable
                $("#panelList_" + panelId).sortable({
                    axis: 'y',
                    items: '.' + CLASSES.panelItem,
                    cursor: 'move',
                    handle: '.' + CLASSES.gripBtn,
                    start: function(e) {
                        $("#panelList_" + panelId).data("sorting", 1);
                    },
                    update: function() {
                        var sorted = $("#panelList_" + panelId).sortable('toArray'),
                        params = {
                            orderId: [],
                            order: []
                        },
                        itemOrder = 1;
	
                        $.each(sorted, function() {
                            if ( this.length <= 0 ) return;
	
                            var itemDom = $('#' + this);
	
                            if ( itemDom.data('order') != itemOrder ) {
                                params.orderId.push(itemDom.data('orderId'));
                                params.order.push(itemOrder);
                            }
                            itemOrder++;
                        });

                        $.post( "./updateOrder.php",
                        {
                            "orderId[]" : params.orderId,
                            "order[]"   : params.order
                        },
                        _confirmUpdateOrder, "xml");
                    }
                });

                if ( _isListView ) {
                    $("#panelList_" + panelId + " ." + CLASSES.gripBtn).show();
                    $("#panelList_" + panelId + " ." + CLASSES.deleteBtn).show();
                } else {
                    $("#panelList_" + panelId).sortable('disable');
                }
            }

            $("#panelList_" + panelId).jScrollPane({
                reinitialiseOnImageLoad: true
            });
        }
    };

    var _confirmUpdateOrder = function($data) {

        var success = $($data).find("Success").text(),
        error   = $($data).find("Error > Message").text(),
        panelId = _panelSet.length + 1,
        sorted  = [],
        itemOrder = 1;

        if ( success.length > 0 ) {
            //          HyperCities.util.debug("Update Order Success");

            // Server update success, so it's safe to update the order at client side
            sorted = $("#panelList_" + panelId).sortable('toArray');

            $.each(sorted, function() {
                if ( this.length <= 0 ) return;

                var itemDom = $('#' + this);

                if ( itemDom.data('order') != itemOrder ) {
                    itemDom.data('order', itemOrder)
                }
                itemOrder++;
            });
        }
        else if ( error.length > 0 ) {
            HyperCities.util.debug("Failed to update order of objects in collection.");
        }
    };

	var _updateNarrative = function ($data) {
//		HyperCities.util.debug(_id + "[A2] Render Narrative Panel");


		var self		   = this,
			panelId        = _panelSet.length + 1,
			collectionXml  = $("Document", $data),
			collectionId   = collectionXml.attr("id"),
			collectionName = collectionXml.find("name:first").text(),
			creator        = collectionXml.find("[nodeName=atom:name]:first").text(),
			description    = collectionXml.find("description:first").text(),
			viewFormat     = collectionXml.find("ExtendedData:first > [nodeName=hc:viewFormat]").text(),
			ownerId        = collectionXml.find("ExtendedData:first > [nodeName=hc:ownerId]").text(),
			stateId        = collectionXml.find("ExtendedData:first > [nodeName=hc:stateId]").text(),
                        baseMap        = collectionXml.find("ExtendedData:first > [nodeName=hc:baseMap]").text(),
			isEditable     = (HyperCities.user.hasUpdatePrivilege(collectionId, ownerId, stateId) && _parentId !== null),
			isDeletable    = (HyperCities.user.hasDeletePrivilege(collectionId, ownerId, stateId) && _parentId !== null),
			timeStamp      = collectionXml.find("TimeStamp:first"),
			timeSpan       = collectionXml.find("TimeSpan:first"),
			timeBegin      = timeSpan.find("begin").text(),
			timeEnd        = timeSpan.find("end").text(),
			timeWhen       = timeStamp.find("when").text(),
			dateFrom       = null,
			dateTo         = null,
			bBox           = _parseBoundingBox(viewFormat),
			domHtml        = [],
			openedList     = HyperCities.collectionList.getOpenedCollections(),
			checkedList    = HyperCities.collectionList.getCheckedCollections(),
			childrenList   = collectionXml.children(),
			totalChildren  = childrenList.length,
			showLoading    = false,
			infoHeight     = 0,
			defaultSpan    = HyperCities.mainMap.getTimespan();

		if ( timeSpan.length > 0 ) { // It's time span
			dateFrom = _parseTimePrimitive(timeBegin);
			dateTo   = _parseTimePrimitive(timeEnd);
		}
		// otherwise look for stamp
		else if ( timeStamp.length > 0 ) {
			dateFrom = _parseTimePrimitive(timeWhen);
			dateTo   = dateFrom.clone();
		}
                // Update URL:
                HyperCities.linkController.updateURL("collections", collectionId);

		// Set Collection Metadata
		domHtml = [ '<div class="', CLASSES.title, '" title="', collectionName, '">', collectionName, '</div>',
					'<div class="', CLASSES.metadata, '">',
					_formatTime(timeBegin, timeEnd, timeWhen), '<br/>',
					'Creator : <span class="', CLASSES.author, '">', creator, '</span></div>',
					'<div class="', CLASSES.description, '">', description, '</div></div>'];

		// Set Timespan to the range of collection
		if ( dateFrom == null ) {
			dateFrom = defaultSpan.min;
		}
		if ( dateTo == null ) {
			dateTo = defaultSpan.max;
		}

		// Save original Timespan, so we can rollback timespan when close panel
		_timespanStack.push({
			timebar: HyperCities.timebar.getTime(),
			mapTime: HyperCities.mainMap.getTimespan()
		});

		// Switch to new timespan
		HyperCities.timebar.setTime(null, dateFrom.getFullYear().toString(), dateTo.getFullYear().toString(), null, true);
		//HyperCities.mainMap.setTimespan({min: dateFrom, max: dateTo}, true);

		// Zoom to collection extent if _zoomToExtent is true
		if ( _zoomToExtent ) {
			_zoomToCollection(bBox);
		}

		$("#panelInfo_" + panelId)
			.data("id", collectionId)
			.data("parentId", _parentId)
			.data("ownerId", ownerId)
			.data("stateId", stateId)
			.data("bBox", bBox)
                        .data("baseMap", baseMap)
			.find("." + CLASSES.loading)
			.after(domHtml.join(''))
			.remove();


		// Add ScrollBar to Description Field
		var maxInfoHeight = ($("#narrativePanelWrapper").height() / 4);
		infoHeight = $("#panelInfo_" + panelId).find("." + CLASSES.description).height();
                if (infoHeight <= maxInfoHeight) {
                    $("#panelInfo_" + panelId)
				.find("." + CLASSES.description)
				.css("height", infoHeight)
                }
		if ( infoHeight > maxInfoHeight && maxInfoHeight > 0) {
			$("#panelInfo_" + panelId)
				.find("." + CLASSES.description)
				.css("height", maxInfoHeight + "px")
				.jScrollPane();
		}

		// Adjust panelList Height
		$("#panelList_" + panelId)
			.data("id", collectionId)
                        // TODO: Correction factor was originally 25, not infoHeight
			.css("height", $('#narrativePanelWrapper').height() - $("#panelInfo_" + panelId).height() - infoHeight);

		// Add Edit/Delete button if user do have privilege
		if ( isEditable ) {

			domHtml = [ '<span class="', CLASSES.editLink, '">Edit</span> | ',
						'<span class="', CLASSES.optionLink, '">Options</span> | ',
						'<span class="', CLASSES.permaLink, '">Link</span>'];

			if ( isDeletable ) {
				domHtml.push(' | <div class="', CLASSES.deleteLink, '"></div>');
			}

			$("#panelInfo_" + panelId)
				.find("." + CLASSES.toolbar)
				.html(domHtml.join(''));
		}

		if ( panelId == 1 ) {
			$("#panelInfo_" + panelId)
				.find("." + CLASSES.title)
				.css("padding-left", "0px").end()
				.find("." + CLASSES.metadata)
				.css("padding-left", "0px");
		}

		if ( typeof (baseMap) != 'undefined' && baseMap != '' && baseMap != null && baseMap != 0 ) {
			HyperCities.mapList.update(HyperCities.mainMap.getBounds(), HyperCities.mainMap.getZoom(), true, true);
			HyperCities.mapList.set("mode", HyperCities.config.MODE_NARRATIVE);
			HyperCities.mapList.addPostSyncOperation( function (baseMap) {
					//HyperCities.debug (_id + "Overlaying basemap " + baseMap);
					HyperCities.mapList.addMap(baseMap);
			}, baseMap );
		}

		// Parse Object Info
		if ( totalChildren > 0 ) {

			// Initialize Progressbar
			if ( !showLoading ) {
				_progressCount = totalChildren;
				showLoading = true;
				HyperCities.mainMap.addProgressbarPending(totalChildren);
			}

			setTimeout( function() {
				var itemDom = childrenList.splice(0,1);

				// Update Progressbar
				_progressCount--;
				setTimeout(HyperCities.mainMap.addProgressbarFinished, 10, 1);

				if ( itemDom[0].nodeName == "NetworkLink" || itemDom[0].nodeName == "Placemark" ) {
					_appendNarrativeItem(itemDom[0], openedList, checkedList, isDeletable);
				}

				if (childrenList.length > 0 && $("#panelList_" + panelId).length > 0) {
					setTimeout(arguments.callee, 10);
				}

			}, 10);
		}
	};
	
    var _closeToolPanel = function () {
        $("#narrativePanelWrapper ."+CLASSES.toolPanel)
        .hide()
        .find("."+CLASSES.toolPanelContent)
        .empty();
    };

    var _createToolPanel = function ($parentDom, $contentDom) {
        var panelId    = $parentDom.data("id"),
        panelWidth = ($parentDom.find("#panelInfo_" + panelId).width() - 2),
        panelTop   = ($parentDom.find("#panelInfo_" + panelId).height() + 15);

        $parentDom.find("."+CLASSES.toolPanel)
        .css("top", panelTop)
        .css("width", panelWidth)
        .find("."+CLASSES.toolPanelContent)
        .empty()
        .append($contentDom).end()
        .show();
    };

    var _openOptionToolPanel = function ($event) {
        var panelDom   = $($event.currentTarget),
        panelId    = panelDom.data("id"),
        optionDom  = ['<div class="', CLASSES.title, '">Customize the display</div>',
        '<div class="', CLASSES.options, '">Sync map</div>',
        ': <span class="', CLASSES.syncMapOn, '">On</span> ',
        '- <span class="', CLASSES.syncMapOff, '">Off</span><br/>',
        '<div class="', CLASSES.options, '">Display mode</div>',
        ': <span class="', CLASSES.showExpanded, '">Expanded</span> ',
        '- <span class="', CLASSES.showList, '">List</span><br/>',
        '<div class="', CLASSES.options, '">Time format</div>',
        ': <span class="', CLASSES.showDate, '">Date</span> ',
        '- <span class="', CLASSES.showDatetime, '">Date and Time</span><br/>',
        '<div class="', CLASSES.options, '">Auto ZoomIn</div>',
        ': <span class="', CLASSES.autoZoomOn, '">On</span> ',
        '- <span class="', CLASSES.autoZoomOff, '">Off</span>'];

        // Only create dom when panel doesn't exist
        if ( panelDom.find("."+CLASSES.options).length == 0 ) {
            _createToolPanel(panelDom, optionDom.join(''));

            // Bind event for option switch
            if ( _isSyncMap ) { // SyncMap On
                panelDom.find("."+CLASSES.syncMapOn).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.syncMapOff).addClass(CLASSES.link);
            }
            else {            // SyncMap Off
                panelDom.find("."+CLASSES.syncMapOff).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.syncMapOn).addClass(CLASSES.link);
            }

            if ( _isListView ) { // List View
                panelDom.find("."+CLASSES.showList).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.showExpanded).addClass(CLASSES.link);
            }
            else { // Expanded View
                panelDom.find("."+CLASSES.showExpanded).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.showList).addClass(CLASSES.link);
            }

            if ( _isDateView ) { // Viwe Date Only
                panelDom.find("."+CLASSES.showDate).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.showDatetime).addClass(CLASSES.link);
            }
            else { // View DateTime
                panelDom.find("."+CLASSES.showDatetime).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.showDate).addClass(CLASSES.link);
            }

            if ( _zoomToExtent ) { // AutoZoom On
                panelDom.find("."+CLASSES.autoZoomOn).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.autoZoomOff).addClass(CLASSES.link);
            }
            else { // AutoZoom Off
                panelDom.find("."+CLASSES.autoZoomOff).addClass(CLASSES.selected);
                panelDom.find("."+CLASSES.autoZoomOn).addClass(CLASSES.link);
            }
        }
    };

    var _openLinkToolPanel = function ($event) {
        var panelDom     = $($event.currentTarget),
        panelId      = panelDom.data("id"),
        collectionId = panelDom.find("#panelInfo_" + panelId).data("id"),
        linkWidth    = (panelDom.find("#panelInfo_" + panelId).width() - 4),
        linkUrl      = $(HyperCities.linkController.generatePermalink('collection', collectionId)).html(),
        linkDom      = ['<div class="', CLASSES.title, '">Use this link to share this collection</div>',
        '<input class="', CLASSES.permaLinkUrl, '" value="', linkUrl, '" readonly="readonly">'];

        // Only create dom when panel doesn't exist
        if ( panelDom.find("."+CLASSES.permaLinkUrl).length == 0 ) {
            _createToolPanel(panelDom, linkDom.join(''));

            // Set Focus auto Select for permaLink Url
            panelDom.find("."+CLASSES.permaLinkUrl)
            .css("width", linkWidth)
            .focus( function() {
                this.select();
            } )
            .select();
        }
    };

    var _overlayBaseMap = function ($mapDate) {
		
        var bounds = HyperCities.mainMap.getBounds(),
        zoom   = HyperCities.mainMap.getZoom(),
        year   = $mapDate.getFullYear().toString();

        HyperCities.mapList.update(bounds, zoom, false, false);

        HyperCities.mapList.overlayBaseMap(year, true);
        $("#loadingMessage").fadeOut("slow");
    };


    return {

        /**
		 * Open NEW Narrative Panel from Collection List
		 * This function is used to initialize the Narrative Mode.
		 * @param {number} collection Id in HyperCities DB
		 */
        load: function($parentId, $collectionId, $options) {
            //			HyperCities.util.debug(_id + "[A2] Load Narrative Panel");
            HyperCities.mainMap.removeCities();

            var options = $options || {};

            if ( typeof(options.zoom) === "boolean" ) {
                _zoomToExtent = options.zoom;
            }

            _parentId = $parentId;

            // Setup System Mode
            _originalMode = HyperCities.session.get("mode");
            HyperCities.session.set("mode", HyperCities.config.MODE_NARRATIVE);

            // Check if already rendered
            if ( (_originalMode === HyperCities.config.MODE_NARRATIVE) && ( _panelSet.length > 0 )&&
                (_panelSet[_panelSet.length-1].collectionId == $collectionId )) {

                // update parentId
                _panelSet[_panelSet.length-1].parentId = _parentId;
                //				HyperCities.util.debug(_id + "Duplicate Narrative Panel " + $collectionId);
                return;
            }

            // Setup NarrativePanel Variables
            _initNarrative();

            // Open Collection if it's not yet opened ??

            // Query Narrative Content
            var params = {
                func : "narrativePanel.getNarrative",
                cid  : $collectionId
            };

            

            $.post("./getNarrative.php", params, _updateNarrative, "xml");
        },

        highlightItem: function($itemId) {
            			//HyperCities.util.debug(_id + "Hover over object " + $itemId);

            var itemIndex = _getObjectIndexById($itemId),
            panelId   = _panelSet.length + 1,
            item, latLng;

            if ( itemIndex >= 0 && _HMarker.isHidden() ) { // It's add in Narrative View
                item = _objects[itemIndex];

                // Get LatLng of Item
                if ( typeof(item) !== 'undefined' && item.type === CLASSES.item ) {
                    if ( item.hidden ) { // item is overlaid by collectionList
                        HyperCities.collectionList.highlightItem($itemId);
                    }
                    else if ( item.overlay instanceof GOverlay ){
                        latLng = item.overlay.getLatLng();
                        if ( latLng instanceof GLatLng ) {
                            _HMarker.setLatLng(latLng);
                            _HMarker.show();
                        }
                    }

                    // Highlight Item in NarrativePanel
                    $("#panel_" + panelId + " ." + CLASSES.panelItem + $itemId).addClass("hover");
                }
            }
            else { // item is overlaid by collectionList
                HyperCities.collectionList.highlightItem($itemId);
            }
            return false;
        },

        unHighlightItem: function($itemId) {
            //			HyperCities.util.debug(_id + "Hover off object " + $itemId);

            var itemIndex = _getObjectIndexById($itemId),
            panelId   = _panelSet.length + 1,
            item;

            if ( itemIndex >= 0 ) {
                item = _objects[itemIndex];
                if ( typeof(item) !== 'undefined' && item.hidden ) { // item is overlaid by collectionList
                    HyperCities.collectionList.unHighlightItem($itemId);
                }
                else if ( _HMarker instanceof GMarker ) {
                    _HMarker.hide();
                }

                // unHighlight Item in NarrativePanel
                $("#panel_" + panelId + " ." + CLASSES.panelItem + $itemId).removeClass("hover");
            }
            else { // item is overlaid by collectionList
                HyperCities.collectionList.unHighlightItem($itemId);
            }

            return false;
        },

        // show Info Windows on map
        showInfoWindow: function($itemId, $collectionId) {

            var objectIndex = _getObjectIndexById($itemId),
            item, options = {};
			
            if ( objectIndex >= 0 ) {
                item = _objects[objectIndex];

                // Make sure we have the information of object
                if ( typeof(item) !== 'undefined' ) {
                    if ( item.hidden ) { // item is overlaid by collectionList
                        HyperCities.collectionList.showInfoWindow($itemId, $collectionId);
                    }
                    else if ( item.overlay instanceof GOverlay ) {
                        //						HyperCities.util.debug(_id + "[A2] Show InfoWindow of Item " + $itemId);

                        // Setup InfoWindow Options
                        options.isCollection = (item.type === CLASSES.collection);
                        if ( typeof($collectionId) !== 'undefined' ) {
                            options.collectionId = $collectionId;
                        }

                        // Open HyperCities InfoWindow
                        HyperCities.mainMap.openHCInfoWindow(item, options);
                    }
                }
            }
            else { // item is overlaid by collectionList
                HyperCities.collectionList.showInfoWindow($itemId, $collectionId);
            }
        },

        showCitation: function ($itemId, $refCode) {
            HyperCities.mainMap.showCitation($itemId, $refCode, _citations[$itemId][$refCode])
            
            // alert(_citations[$itemId][$refCode]);
            
        },

        panToItem: function($itemId, $options) {

            var options    = $options || {},
            openWindow = (options.openWindow === true),
            itemIndex  = _getObjectIndexById($itemId),
            item, latLng;

            if ( itemIndex >= 0 ) {
                item = _objects[itemIndex];

                // Get LatLng of Item
                if (( typeof(item) !== 'undefined' ) &&
                    ( item.type === CLASSES.item ) &&
                    ( item.overlay instanceof GOverlay)) {

                    latLng = item.overlay.getLatLng();
                    if ( latLng instanceof GLatLng ) {
                        HyperCities.mainMap.panTo(latLng);

                        if ( _isSyncMap ) {
                            _overlayBaseMap(item.dateFrom);
                        }
                    }
                }
            }
        },

        /**
		 * Compute CSS parameters for Narrative Panel
		 * Should be called when the size of sidebar changes
		 */
        checkResize: function() {

            var viewportHeight = $(window).height(),
            sidebarWidth   = $('#sidebarWrapper').width(),
            offsetTop      = 125,
            panelLength    = _panelSet.length + 1,
            toolPanelWidth = 0,
            toolPanelTop   = 0;

            $("#narrativePanelWrapper").css("width", sidebarWidth + "px");

            if ( $("#narrativePanelWrapper").is(":visible") ) {
                $("#narrativePanelWrapper ." + CLASSES.panel).each( function() {
                    var offsetLeft = ( $(this).data("id") - panelLength ) * sidebarWidth;

                    $(this).css("width", (sidebarWidth - 10 ) + "px");
                    $(this).css("left", offsetLeft + "px");
                });

                $("#narrativePanelWrapper .jScrollPaneContainer").css("width", "auto");
                $("#narrativePanelWrapper ." + CLASSES.panelList)
                .css("height", viewportHeight - offsetTop)
                .jScrollPane();

                // Resize Tool Panel
                toolPanelWidth = ($("#panelInfo_" + panelLength).width() - 2);
                toolPanelTop   = ($("#panelInfo_" + panelLength).height() + 15);

                $("#narrativePanelWrapper ."+CLASSES.toolPanel)
                .css("top", toolPanelTop)
                .css("width", toolPanelWidth);

                // Resize Collection Description Area
                $("#narrativePanelWrapper ." + CLASSES.panelInfo + " ." + CLASSES.description)
                .jScrollPane();
            }
        },

        getOpenedPanelIds: function () {
            var panelIds = [];
            HyperCities.util.debug(_panelSet);
            for (var i in _panelSet) {
                panelIds.push(_panelSet[i].collectionId);
            }
            return panelIds;
        } // end getOpenedPanels: function ()
    }; // end of public methods
}(); // end of Object

// end of file
