
// fake the namespace definition
if (typeof ERDAS === "undefined") {

    var ERDAS = {};
}

ERDAS.catalog = {};
ERDAS.catalog.misc = ERDAS.catalog.misc || {};


ERDAS.catalog.UI = function() {

}


ERDAS.catalog.misc.arrayContains = function (array, element) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == element) {
            return true;
        }
    }
    return false;
}

ERDAS.catalog.misc.arrayRemove = function (array, element) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == element) {
            array.splice(i,1);
            return true;
        }
    }
    return false;
}


/* *******************************************
              Babel UI Definition
   ******************************************* */

/**
 * Defines the UI singleton.
 * The getInstance method is the entry point to deal with the whole client.
 */
ERDAS.catalog.UI.getInstance = function() {
    var _instance;
    return function () {
        if (! _instance) _instance = new ERDAS.catalog.UI();
        return _instance;
    };
}();

ERDAS.catalog.UI.prototype = {

    restService: null,
    baseUrl: null,
    map: null,
    query: null,
    overviewMap: null,
    taxonomyTree: null,
    advancedSearchPanel: null,
    isCtrlDown: false,
    isAltDown: false,
    currentEditedNode: null,
    currentEditedValue: null,

    displayHelp: function() {
        modifyCssClass(".help", "display", "block");
    },

    createGlobalKeyDownCapture: function() {
        var this_ = this;
        return function(e) {
            if (!e) e = window.event;

            if (e.ctrlKey) {
                this_.isCtrlDown = true;
            }

            if (e.altKey) {
                this_.isAltDown = true;
            }

            if (e.ctrlKey && e.altKey) {
                this_.displayHelp();
            }

        }
    },

    createGlobalKeyUpCapture: function() {
        var this_ = this;
        return function(e) {
            if (!e) e = window.event;

            this_.isCtrlDown = false;
            this_.isAltDown = false;
            modifyCssClass(".help", "display", "none");
        }
    },

    init: function(baseURL, baseRestURL, useTilapia) {
        this.baseUrl = baseURL;
        this.restService = new ERDAS.catalog.RestService(baseRestURL);

        if (useTilapia) {
            this.map = new ERDAS.catalog.Map();
        }
        // Uncomment this to activate help hotkeys
        document.onkeydown = this.createGlobalKeyDownCapture();
        document.onkeyup = this.createGlobalKeyUpCapture();
    },

    initUI: function() {
        this.overviewMap = document.getElementById('overviewMap');
        if (this.map && this.overviewMap && !this.map.map) {
            this.overviewMap.style.display = '';
            this.map.init('overviewMap');
        }

        this.advancedSearchPanel = document.getElementById('advancedSearchPanel');
        this.advancedSearchPanel.orderBy = document.getElementById('orderBySelect');
        this.advancedSearchPanel.orderDir = document.getElementById('orderByDir');
    },

    login: function(login, password) {
        ERDAS.catalog.misc.callHTTP(this.baseUrl+"/j_spring_security_check?j_username="+login+"&j_password="+password,
                            "POST",
                            null,
                            function() {document.location.reload()},
							function(req) {
                                if (req.status == 404) {document.location.reload()}
                                else if (req.status == 401) {ERDAS.catalog.UI.getInstance().displayHeaderMessage(true, '<span style="color:#c00000">Invalid login/password</span>')}
                                else ERDAS.catalog.misc.DEFAULT_ERROR_CALLBACK(req);
                            });
	},

    logout: function() {

        var ui = this;

        ERDAS.catalog.misc.callHTTP(this.baseUrl+"/j_spring_security_logout",
                            "POST",
							null,
							function() {document.location = ui.baseUrl},
							function(req) {
                                if (req.status == 404) {document.location = ui.baseUrl}
                                else ERDAS.catalog.misc.DEFAULT_ERROR_CALLBACK(req);
                            });
    },

    displayLogin: function() {
        var loginForm = document.getElementById('loginForm');
        loginForm.style.display = 'inline';
    },

    showProgress: function(visible) {
        if (visible) this.displayHeaderMessage(false);
        document.getElementById('progressbar').style.display = visible?'inline':'none';
    },

    displayHeaderMessage: function(visible, message) {
        var messageDiv = document.getElementById('headerMessage');
        if (message) messageDiv.innerHTML = message;
        messageDiv.style.display = visible?'block':'none';
    },

    displayObject: function (identifier) { document.location = this.restService.getAccessUrl(identifier) },

    displayPopup: function (url) {
        window.open(url, 'BABEL_POPUP', 'height=200, width=400, toolbar=no, menubar=no, scrollbars=no, location=no, directories=no, status=no, top=200, left=300');
    },

    displayBrokenImage: function(imgElement) {
        imgElement.src = this.baseUrl+"/images/file_broken.png";
        imgElement.style.border = "none";
    },

    displayLoadingImage: function(imgElement) {
        imgElement.src = this.baseUrl+"/images/loading_clock.gif";
    },

    toggleSearchPanel: function() {
        var button = document.getElementById("leftPanelButton");
        if (this.advancedSearchPanel.style.display == 'none') {
            button.src = this.baseUrl+'/images/leftArrow.png';
            this.advancedSearchPanel.style.display = 'block';
        } else {
            this.advancedSearchPanel.style.display = 'none';
            button.src = this.baseUrl+'/images/rightArrow.png';
        }
    },

    updateAdvancedSearchPanel: function(query) {
        if (this.advancedSearchPanel && this.advancedSearchPanel.orderBy) {
            for (var idx=0;idx<this.advancedSearchPanel.orderBy.options.length;idx++) {
                if (this.advancedSearchPanel.orderBy.options[idx].value == query.orderby) {
                    this.advancedSearchPanel.orderBy.selectedIndex = idx;
                }
            }
        }

        if (this.advancedSearchPanel && this.advancedSearchPanel.orderDir) {
            this.advancedSearchPanel.orderDir.selectedIndex = query.orderDesc?1:0;
        }
    },

    /*
    showAdvancedSearch: function() {

        var elem = document.getElementById('advancedSearch');

        if (this.map) {
            if (elem.style.display == 'none') {
                this.overviewMap.style.display = 'block';
                this.overviewMap.style.top = this.overviewMap.offsetTop-5+'px';
                this.overviewMap.style.left = this.overviewMap.offsetLeft-10+'px';
                this.overviewMap.style.position = 'absolute';
                this.map.autoSubmitOnSelect = false;
            } else {
                this.overviewMap.style.display = this.map.isVisible?'block':'none';
                this.overviewMap.style.top = '';
                this.overviewMap.style.left = '';
                this.overviewMap.style.position = '';
                this.overviewMap.style.float = 'right';
                this.map.autoSubmitOnSelect = true;
            }
        }

        toggleVisibility(elem);
    },
    */

    setQuery: function(queryData) {
        this.query = new ERDAS.catalog.Query(this.restService.restBaseUrl, queryData);
        this.updateAdvancedSearchPanel(this.query);
    },

    submitQuery: function(simpleQuery) {
        this.query.adv = this.advancedSearchPanel && (this.advancedSearchPanel.style.display != 'none');
        if (this.query.classes && this.query.classes.length>0) this.query.resourcePath = '/items';
        this.query.submit(simpleQuery);
    },

    displayOnMap: function (id, geom) {
        if (this.map) {
            this.map.addDisplayedItem(id, geom);
        }
    },

    addResourceToMap: function (serviceUrl, resourceName, version) {
        if (this.map) {
            return this.map.addMapResource(serviceUrl, resourceName, version);
        } else {
            return null;
        }
    },

    removeResourceFromMap: function (layerDescriptor) {
        if (this.map) {
            this.map.removeMapResource(layerDescriptor);
        }
    },

    highlightItem: function (itemId, toggle) {
        if (this.map) this.map.highlightItem(itemId, toggle);
    },

    taxonomyTreeInit: function(schemes, focusedCs, focusedConceptId, excludedSchemes) {
        this.taxonomyTree = new YAHOO.widget.TreeView("taxonomyBrowser");
        this.taxonomyTree.setDynamicLoad(this.loadDataForNode);
        var root = this.taxonomyTree.getRoot();
        var csRoot;
        for (var idx=0;idx<schemes.length;idx++) {
            var scheme = schemes[idx];
            if (!excludedSchemes || !ERDAS.catalog.misc.arrayContains(excludedSchemes, scheme.identifier)) {
                csRoot = new YAHOO.widget.HTMLNode({html:((scheme.title==null || scheme.title=='')?scheme.name:scheme.title),id:scheme.id,identifier:scheme.identifier,isCs:true}, root, false);
                csRoot.multiExpand = false;
                if (focusedCs && scheme.id == focusedCs.id) {
                    this.fillNodeChildren(csRoot, focusedCs.childrenConcepts, true);
                }
            }
        }

        this.taxonomyTree.subscribe("clickEvent", function(node) {
               if (node.node.data.isClass) {
                   // find items of class
                   if (ERDAS.catalog.UI.getInstance().isCtrlDown) {
                       // multi clicks on a class

                       if (ERDAS.catalog.misc.isClassActive(node.node.getContentEl(), 'selectedNode')) {
                           ERDAS.catalog.misc.setClass(node.node.getContentEl(), 'selectedNode', false);
                           ERDAS.catalog.misc.arrayRemove(
                               ERDAS.catalog.UI.getInstance().query.classes,
                               node.node.data.id);
                       } else {
                           ERDAS.catalog.misc.setClass(node.node.getContentEl(), 'selectedNode', true);
                           ERDAS.catalog.UI.getInstance().query.classes[ERDAS.catalog.UI.getInstance().query.classes.length] = node.node.data.id;
                       }

                   } else {
                       // single click on a class
                       ERDAS.catalog.UI.getInstance().query.classes = [node.node.data.id];
                       ERDAS.catalog.UI.getInstance().submitQuery();
                   }
               } else if (!node.node.data.isCs) {
                   // single click on a concept
                   if (ERDAS.catalog.UI.getInstance().isAltDown) {
                       // classify an object
                       ERDAS.catalog.UI.getInstance().restService.classify(ERDAS.catalog.UI.getInstance().query.identifier, node.node.data.identifier);
                   } else {
                       // find classifiedAs
                       ERDAS.catalog.UI.getInstance().query.classifiedAs = [node.node.data.identifier];
                       ERDAS.catalog.UI.getInstance().submitQuery();

                       //document.location = ERDAS.catalog.UI.getInstance().restService.restBaseUrl +
                       //                '/concepts/' + node.node.data.id + '/classifiedObjects';
                   }

               }
               document.getElementById('typeSelect').selectedIndex = -1;
               return false;
            });

        this.taxonomyTree.subscribe("dblClickEvent", function(node) {
            if (node.node.data.isClass) {
                var newLocation = ERDAS.catalog.UI.getInstance().restService.restBaseUrl +
                                       '/mappings/' + node.node.data.id;
                document.location = newLocation;

                return false;
            } else {
                var newLocation = ERDAS.catalog.UI.getInstance().restService.restBaseUrl +
                                       '/items/' + node.node.data.id;
                if (!node.node.data.isCs) newLocation += '?conceptFocus='+node.node.data.id;
                else newLocation += '?adv=true';
                document.location = newLocation;

                return false;
            }
        });


        this.taxonomyTree.render();
        if (focusedConceptId) {
            var focusedConcept = this.taxonomyTree.getNodeByProperty('id', focusedConceptId);
            focusedConcept.expand();
            focusedConcept.focus();
            ERDAS.catalog.misc.setClass(focusedConcept.getContentEl(), 'selectedNode', true);
        }
    },

    addTypesTree: function(rootNode, focusedTypes, rootNodeName) {

        var root = this.taxonomyTree.getRoot();
        var typesRoot = new YAHOO.widget.HTMLNode(
            { html:rootNodeName?rootNodeName:rootNode.mappedClass.substring(rootNode.mappedClass.lastIndexOf('.')+1),
              id:rootNode.mappedClass,
              isClass:true},
            root, false);
        typesRoot.multiExpand = true;
        this.fillTypeNodeChildren(typesRoot, rootNode.childrenMappings, true);

        this.taxonomyTree.render();

        if (focusedTypes) {
            for (var idx=0;idx<focusedTypes.length;idx++) {
                var focusedtype = this.taxonomyTree.getNodeByProperty('id', focusedTypes[idx]);
                if (focusedtype) {
                    focusedtype.expand();
                    focusedtype.focus();
                    ERDAS.catalog.misc.setClass(focusedtype.getContentEl(), 'selectedNode', true);
                }
            }
        }
    },

    loadDataForNode : function(node, onCompleteCallback) {

       ERDAS.catalog.UI.getInstance().restService.findById(
           node.data.id,
           function(resp) {
               var childrenConcepts = resp.results[0].childrenConcepts;
               ERDAS.catalog.UI.getInstance().fillNodeChildren(node, childrenConcepts, true);

               onCompleteCallback();
           },
           null, 'tree');
    },

    fillNodeChildren : function(node, childrenConcepts, markAsComplete) {
       for (var idx=0;idx<childrenConcepts.length;idx++) {
           var child = childrenConcepts[idx];
           var classifiedCount = (child.classifiedObjectsCount) + (child.typedObjectsCount);
           var childNode = new YAHOO.widget.HTMLNode({html:((child.title==null || child.title=='')?child.name:child.title)+(classifiedCount==0?'':' ('+classifiedCount+')'),id:child.id,identifier:child.identifier}, node, false);
           childNode.multiExpand = false;
           childNode.dynamicLoadComplete = markAsComplete;
           if (child.childrenConcepts) this.fillNodeChildren(childNode, child.childrenConcepts, markAsComplete);
       }
        node.dynamicLoadComplete = markAsComplete;
    },

    fillTypeNodeChildren : function(node, childrenTypes, markAsComplete) {
       for (var idx=0;idx<childrenTypes.length;idx++) {
           var child = childrenTypes[idx];
           var childNode = new YAHOO.widget.HTMLNode(
              {  html:(child.mappedClass?child.mappedClass.substring(child.mappedClass.lastIndexOf('.')+1):''),
                 id:child.mappedClass,
                 isClass:true},
              node, false);
           childNode.multiExpand = true;
           childNode.dynamicLoadComplete = markAsComplete;
           if (child.childrenMappings) this.fillTypeNodeChildren(childNode, child.childrenMappings, markAsComplete);
       }
        node.dynamicLoadComplete = markAsComplete;
    },

    displayEditProperty: function(identifier, propertyName, containerNode) {

        // revert current edition
        if (this.currentEditedNode) this.currentEditedNode.innerHTML = this.currentEditedValue;

        this.currentEditedNode = containerNode;
        this.currentEditedValue = containerNode.innerHTML;
        containerNode.innerHTML = "<form onsubmit=\"ERDAS.catalog.UI.getInstance().restService.setProperty('"+identifier+"','"+propertyName+"', this.propValue.value, function(newValue){return function() {ERDAS.catalog.UI.getInstance().currentEditedNode.innerHTML = newValue};}(this.propValue.value))\">" +
                                  "<input name='propValue' value='"+this.currentEditedValue+"' size='20'></form>";
    },

    displayEditPropertyName: function(identifier, propertyName, containerNode) {

        // revert current edition
        if (this.currentEditedNode) this.currentEditedNode.innerHTML = this.currentEditedValue;

        this.currentEditedNode = containerNode;
        this.currentEditedValue = containerNode.innerHTML;
        containerNode.innerHTML = "<form onsubmit=\"ERDAS.catalog.UI.getInstance().restService.renameProperty('"+identifier+"','"+propertyName+"', this.propValue.value, function(newValue){return function() {ERDAS.catalog.UI.getInstance().currentEditedNode.innerHTML = newValue};}(this.propValue.value))\">" +
                                  "<input name='propValue' value='"+this.currentEditedValue+"' size='20'></form>";
    }
}

ERDAS.catalog.UI.Profile = function() {

}

ERDAS.catalog.UI.Profile.prototype = {

    searchTypes: new Array(),

    getSearchTypes: function() {return this.searchTypes}
}




/* *******************************************
              Babel Query Definition
   ******************************************* */

/**
 * Build a query object from a data array.
 * The data array should contain the following fields :
 * resourcePath, keywords, intersect, orderby, maxResults, start .
 * @param restRoot rest endpoint of ther service
 * @param data array cointainig the query parameters
 */
ERDAS.catalog.Query = function(restRoot, data) {
    this.restRoot     = restRoot;
    this.resourcePath = data.resourcePath;
    this.keywords     = data.keywords;
    this.intersect    = data.intersect;
    this.bbox         = data.bbox;
    if (data.orderby) {
        var args = data.orderby.split(" ");
        this.orderby = args[0];
        if (args.length==2 && args[1] == 'desc') this.orderDesc= true;
    }
    this.maxresults   = data.maxresults;
    this.start        = data.start;
    this.hql          = data.hql;
    this.inurl        = data.inurl;
    this.adv          = data.adv;
    this.identifier   = data.identifier;
    this.classes      = data.classes?data.classes:[];
    this.classifiedAs = data.classifiedAs?data.classifiedAs:[];
}

ERDAS.catalog.Query.prototype = {

    restRoot: null,

    resourcePath: '/items',
    maxresults: 10,
    start: 0,
    keywords: null,
    intersect: null,
    bbox: null,
    orderby: null,
    hql: null,
    identifier: null,
    inurl: null,
    classes:null,
    classifiedAs:null,
    orderDesc:false,

    createSimpleQuery: function() {
        return (this.keywords||'') +
               (this.intersect?(' intersect:'+this.intersect):'') +
               (this.bbox?(' bbox:'+this.bbox):'') +
               //(this.orderby?(' orderby:'+this.orderby):'') +
               (this.inurl?(' inurl:'+this.inurl):'');
    },

    submit: function(simpleQuery) {

        // hack to avoid having the spatial filter warning when switching object types
        if (simpleQuery != null && simpleQuery.indexOf('intersect')<0 ) this.intersect = null;
        if (simpleQuery != null && simpleQuery.indexOf('bbox')<0 ) this.bbox = null;

        if ((this.bbox || this.intersect) &&
            ERDAS.catalog.UI.getInstance().query.resourcePath.indexOf("resources")<0 &&
            ERDAS.catalog.UI.getInstance().query.resourcePath != '/items') {
            alert("Only service resources (map layers, coverages, feature types) can be spatially queried." +
                  "Please select an appropriate object type or remove the spatial filter.");

            return false;
        }

        var newUrl = this.restRoot + this.resourcePath;
        newUrl += "?q=" + (simpleQuery != null ? encodeURIComponent(simpleQuery) : (encodeURIComponent(this.createSimpleQuery())));
        newUrl += (this.maxresults?'&maxresults='+this.maxresults:'');
        if (this.classes && this.classes.length>0) {
            var classesStr = this.classes[0];
            for (var idx=1;idx<this.classes.length;idx++) classesStr += ','+this.classes[idx];
            newUrl += '&classes=' + classesStr;
        }
        if (this.classifiedAs && this.classifiedAs.length>0) {
            var classifiedAsStr = this.classifiedAs[0];
            for (var idx=1;idx<this.classifiedAs.length;idx++) classifiedAsStr += ','+this.classifiedAs[idx];
            newUrl += '&classifiedAs=' + encodeURIComponent(classifiedAsStr);
        }
        newUrl += (this.orderby ? ('&orderBy=' + this.orderby +(this.orderDesc?' desc':' asc')): '');
        newUrl += (this.start ? '&start=' + this.start : '');
        /*
        newUrl += (this.bbox ? '&bbox=' + this.bbox : '');
        newUrl += (this.intersect ? '&intersect=' + this.intersect : '');
        */
        newUrl += (this.adv ? '&adv=' + this.adv : '');
        newUrl += (this.hql ? '&hql=' + encodeURIComponent(this.hql) : '');
        document.location = newUrl;
    },

    setIntersect: function(geom) {
        this.intersect = geom;
        //TODO update query panel
    }

}




/* *******************************************
        Babel REST Service Definition
   ******************************************* */

/**
 * Constructor.
 * @param url base url of the rest service, e.g. http://localhost/babel-service/catalog/content
 */
ERDAS.catalog.RestService = function(url) {
    this.restBaseUrl = url;
}

ERDAS.catalog.RestService.prototype = {

    restBaseUrl: null,


    /**
     * Classify a catalogItem with a concept
     * @param identifier item identifier
     * @param conceptUri concept identifier
     * @param callback callback function called after deletion
     */
    classify: function(identifier, conceptUri, callback) {
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier)+"/classifyingConcepts",
                            "POST",
                            conceptUri,
                            callback,
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    /**
     * Removes a catalogItem from the catalog
     * @param identifier item identifier
     * @param callback callback function called after deletion
     */
    remove: function(identifier, callback) {
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier),
                            "DELETE",
                            null,
                            callback,
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    /**
     * Removes a property for the given item
     * @param identifier item identifier
     * @param propertyName name of the property
     * @param callback callback function called after deletion
     */
    removeProperty: function(identifier, propertyName, callback) {
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier)+'/'+propertyName,
                            "DELETE",
                            null,
                            callback,
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    setProperty: function(identifier, propertyName, propertyValue, callback) {
        var queryString = "value="+encodeURIComponent(propertyValue);
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier)+'/'+propertyName,
                            "POST",
                            queryString,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json",
                            "application/x-www-form-urlencoded");
    },

    renameProperty: function(identifier, propertyName, newPropertyName, callback) {
        var queryString = "rename="+encodeURIComponent(newPropertyName);
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier)+'/'+propertyName,
                            "POST",
                            queryString,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json",
                            "application/x-www-form-urlencoded");
    },

    addFileAttachment: function(identifier, attachmentName, form, callback) {
        form.method = 'POST';
        form.enctype = 'multipart/form-data';
        form.action=this.getAccessUrl(identifier)+'/attachment/'+attachmentName;

        form.onsubmit = null;

        //document.getElementById('waitMessage').style.display='block';
        form.submit();
    },

    /**
     * Removes a property for the given item
     * @param identifier item identifier
     * @param propertyName name of the property
     * @param callback callback function called after deletion
     */
    removeAttachment: function(identifier, attachmentName, callback) {
        ERDAS.catalog.misc.callHTTP(this.getAccessUrl(identifier)+'/attachment/'+attachmentName,
                            "DELETE",
                            null,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    addUrlAttachment: function(identifier, attachmentName, url, mimetype, callback) {

        var resourceUrl = this.restBaseUrl + '/items/'+identifier+'/attachment/'+attachmentName;
        var queryString = "resourceUrl="+encodeURIComponent(url);
        if (mimetype) queryString += "resourceType="+encodeURIComponent(mimetype);

        //document.getElementById('waitMessage').style.display='block';
        ERDAS.catalog.misc.callHTTP(resourceUrl,
                            "POST",
                            queryString,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            function(req) {ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK(req)},
                            "application/json",
                            "application/x-www-form-urlencoded");

    },

    harvestUrl: function(url, resourceSubPath, callback, errorCallback, reharvest) {
        var resourceUrl = this.restBaseUrl;
        if (resourceSubPath) resourceUrl += resourceSubPath;
        var queryString = "resourceUrl="+encodeURIComponent(url);
        queryString += "&profile=summary&reharvest="+(reharvest?'true':'false');
        ERDAS.catalog.misc.callHTTP(resourceUrl,
                            "POST",
                            queryString,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            errorCallback || ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json",
                            "application/x-www-form-urlencoded");
    },

    harvestText: function(text, resourceSubPath, callback, errorCallback, reharvest) {
        var resourceUrl = this.restBaseUrl;
        if (resourceSubPath) resourceUrl += resourceSubPath;
        resourceUrl += "&profile=summary&reharvest="+(reharvest?'true':'false');
        ERDAS.catalog.misc.callHTTP(resourceUrl,
                            "POST",
                            text,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            errorCallback || ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    /*
    reharvest: function(id, url, serviceType, callback) {
		var serviceType = '';
		var start = -1;
		if ((start = url.indexOf("service=")) === -1) {
			alert("The url [" + url + "] is not valid : missing 'service' parameter");
			return false;
		}
		var end = -1;
		if ((end = url.indexOf("&"), start) === -1) {
			serviceType = url.substring(start);
		} else {
			serviceType = url.substring(start, end);
		}
		this.harvestUrl(url, serviceType, callback)
	},
	*/

    reindex: function(callback) {
        ERDAS.catalog.misc.callHTTP(this.restBaseUrl+"/admin?cmd=reindex",
                            "POST",
                            null,
                            callback,
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    flushCache: function(callback) {
        ERDAS.catalog.misc.callHTTP(this.restBaseUrl+"/admin?cmd=flushCache",
                            "POST",
                            null,
                            callback,
                            ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    post: function(object, callback) {

    },

    findById: function (id, callback, errorCallback, profile) {
        var url = this.restBaseUrl+"/items/"+encodeURIComponent(id);
        if (profile) url += "?profile="+profile;
        ERDAS.catalog.misc.callHTTP(url,
                            "GET",
                            null,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            errorCallback || ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    findByIdentifier: function (identifier, callback, errorCallback, profile) {
        var url = this.restBaseUrl+"/items?identifier="+encodeURIComponent(identifier);
        if (profile) url += "&profile="+profile;
        ERDAS.catalog.misc.callHTTP(url,
                            "GET",
                            null,
                            ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK(callback),
                            errorCallback || ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK,
                            "application/json");
    },

    getAccessUrl: function(identifier) {
        return this.restBaseUrl+"/items/"+encodeURIComponent(identifier);
    }
}

ERDAS.catalog.RestService.DEFAULT_ERROR_CALLBACK = function(req)
{
    var errorObj = eval("("+req.responseText+")");

    var message = errorObj.errorMessage || errorObj.error;

    var conf = confirm (message +
                        ". Do you want to see the complete error message?");

    if (conf) {
        var win = window.open ("", "Error message",
                'scrollbars=1,resizable=1,menubar=0');
        win.document.documentElement.innerHTML =
            "<b>"+(errorObj.error || "")+"</b><BR>"+
            "<pre>"+errorObj.stacktrace+"</pre>";
    }
};

ERDAS.catalog.RestService.DEFAULT_JSON_CALLBACK = function(callback) {
    if (callback) {
        return function(req) {
            if (req.responseText) {
                callback(eval("(" + req.responseText + ")"));
            } else {
                callback();
            }
        };
    }
    else return null;
};


/* *******************************************
         Babel Map component definition
   ******************************************* */

ERDAS.catalog.Map = function() {

}

ERDAS.catalog.Map.prototype = {

    displayedItems: {},
    globalBbox: null,
    containerId: null,
    map: null,
    autoSubmitOnSelect: true,
    isVisible: false,
    tool: null,

    normalStyle: null,
    highlightedStyle: null,

    init: function(containerId) {

        this.tool = new ERDAS.services.ServiceTool ();

        this.normalStyle = new ERDAS.maps.Map.DrawingOptions(1, "#333377", 1.0, "#0000d0", 0 /* 0.05 */);
        this.highlightedStyle = new ERDAS.maps.Map.DrawingOptions(2, "#008800", 1.0, "#008800", 0.2);

        this.containerId = containerId;

        this.map = new ERDAS.maps.Map (this.containerId,{
                width: 200,
                height: 150,
                noServerSide : true
        });



        this.map.addLayerDescriptor(this.createLayerDescriptor(
                'http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE',
                'cntry98gen02',
                [-180,-90,180,90,4326],
                "1.1.0"));
        /*
        this.map.addLayerDescriptor(this.createLayerDescriptor(
                'http://www2.demis.nl/wms/wms.asp?wms=WorldMap',
                'Hillshading',
                [-180,-90,180,90,4326]));

        this.map.addLayerDescriptor(this.createLayerDescriptor(
                'http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE',
                //'cntry98gen02',
                'cntry98',
                [-180,-90,180,90,4326]));

        this.map.addLayerDescriptor(this.createLayerDescriptor(
                'http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE',
                'admin98',
                [-180,-90,180,90,4326]));
        this.map.addLayerDescriptor(this.createLayerDescriptor(
                'http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE',
                'cities',
                [-180,-90,180,90,4326]));
                */


        this.map.eventProcessor.selectAction ("navigate");
        var catalogMap = this;
        this.map.onSelectedBoxChanged.subscribe (function (type, args) {
            var box = args [0];
            catalogMap.map.eventProcessor.selectAction ("navigate");
            if (box) {
                ERDAS.catalog.UI.getInstance().query.setIntersect("BBOX("+(box.minx+'').substring(0, 7)+" "+(box.miny+'').substring(0, 7)+","+(box.maxx+'').substring(0, 7)+" "+(box.maxy+'').substring(0, 7)+")");
                if (catalogMap.autoSubmitOnSelect) ERDAS.catalog.UI.getInstance().submitQuery();
            }
        });


        if (this.globalBbox) {
            this.globalBbox.expand(1.4);
            this.map.setBox(this.globalBbox);
        }

        var hasElements = false;
        for (var idx in this.displayedItems) {
            this.displayedItems[idx].shownGeom = this.map.showGeometry(this.displayedItems[idx].geom, this.normalStyle);
            hasElements = true;
        }

        if (hasElements) this.enable(true);

        //this.highlightItems(this.displayedItems);
        //this.map.eventProcessor.selectAction ("highlight");


    },

    enable: function(isEnabled) {
        this.isVisible = isEnabled;
        document.getElementById(this.containerId).style.display = isEnabled?'block':'none';
    },

    drawBoxFilter: function() {
        this.map.eventProcessor.selectAction ("geom-selectbox");
    },

    highlightItem: function (itemId, toggle) {
        if (this.displayedItems[itemId]) {
            var oldGeomId = this.displayedItems[itemId].shownGeom;
            if (toggle)
                this.displayedItems[itemId].shownGeom = this.map.showGeometry (this.displayedItems[itemId].geom, this.highlightedStyle);
            else
                this.displayedItems[itemId].shownGeom = this.map.showGeometry (this.displayedItems[itemId].geom, this.normalStyle);

            if (oldGeomId) this.map.getGeometryEditingLayerDescriptor().removeGeometryById (oldGeomId);
        }

    },

    highlightItems: function (items) {

        var vmp = this.map.getViewMouseProcessor ();
        var registeredItems = items;
        var handler = ERDAS.catalog.Map.createMouseMoveHandler(this.map, this.highlightedStyle);
        vmp.registerAction ("highlight", [ "mousemove" ], function (vmp, event, downAt, upAt) {
            handler (upAt.point, registeredItems);
        });
    },

    addDisplayedItem: function (id, geom) {
        this.displayedItems[id] = {id:id, geom:geom};
        if (!this.globalBbox) this.globalBbox = geom.getEnvelope();
        else this.globalBbox.growWithGeometry(geom);
    },

    addMapResource: function (serviceUrl, resourceName, version) {
        var ld = this.createLayerDescriptor(
                serviceUrl,
                resourceName,
                [-180,-90,180,90,4326], version);
        this.map.addLayerDescriptor(ld);
        return ld;
    },

    removeMapResource: function (layerDescriptor) {
        this.map.removeLayerDescriptor(layerDescriptor);
    },

    createLayerDescriptor: function(serviceUrl, layerName, bbox, version) {

        // Search/create the service
        var service = this.tool.getWMSService (serviceUrl);
        if (! service) {

            // No such service yet? Create it and reference it.
            service = new ERDAS.services.WMSService (
                    {
            url:serviceUrl,
            type: 'WMS',
            version: version}
                    );
            //this.tool.storeService (service);
        }
        test = service;
        // Prepare an object holding all the necessary information
        // (PhD, basically, you have this from the catalog)
        var layerInformation =
        {
                serviceUrl  : serviceUrl,
                serviceType : "WMS",
                name        : layerName,
                bboxes      : [bbox],
                nativelySupportedSrs : [4326],
                imageFormats : [
                         "image/gif",
                         "image/jpeg",
                         "image/png"]
        };

        // Add the dataset
        service.addLayer (layerInformation);

        // From the newly-added dataset, create a map layer
        return service.createLayerDescriptor (layerName);
    }
}

ERDAS.catalog.Map.createMouseMoveHandler = function(map, highlightedStyle) {

    var currentArray = new Array();

    return function(point, items) {

        var i, id;

        for (var currentIdx in currentArray) {
            var current = currentArray[currentIdx];
            if (current && !ERDAS.catalog.Map.isInGeometry (point, current.item.geom)) {
                map.getGeometryEditingLayerDescriptor().removeGeometryById (current.id);
                ERDAS.catalog.misc.setClass(document.getElementById(current.item.id), " selected", false);
                currentArray[currentIdx] = undefined;
            }
        }
                   //map.getGeometryEditingLayerDescriptor().getRenderer().getNodeForGeometry()
                   //map.getGeometryEditingLayerDescriptor().getRenderer().getNodeForGeometry('g_10geomId').childNodes[0].onmouseover = function(){alert('test')}
        for (var idx in items) {

            if (ERDAS.catalog.Map.isInGeometry (point, items[idx].geom)) {
                id = map.showGeometry (items[idx].geom, highlightedStyle);
                currentArray.push({ item : items[idx],
                                    id   : id });
                ERDAS.catalog.misc.setClass(document.getElementById(items[idx].id), " selected", true);
            }
        }

    }
}

ERDAS.catalog.Map.isInGeometry = function (point, geom) {
    // If the point is not even in the bounding box, it cannot be in the geometry
    if (!geom.getEnvelope ().contains (point)) return false;

    return geom.contains (point);
}




/* *******************************************
              Babel Misc utils
   ******************************************* */

/**
 * @param {function} callback the callback called when the request has
 *   successfully completed.  It takes the request as an argument.
 * @param {function} errorCallback (Optional) Function called when the request
 *   code is not 200.  It takes the request as an argument.
 */
ERDAS.catalog.misc.callHTTP = function(url, method, body, callback, errorCallback, accept, bodyType)
{
    var req = XMLHTTPObject();

    req.onreadystatechange = function () {
        if (req.readyState == 4)
            if (req.status >= 400) {
                ERDAS.catalog.UI.getInstance().showProgress(false);

                if (errorCallback)
                    errorCallback(req);
                else
                    ERDAS.catalog.misc.DEFAULT_ERROR_CALLBACK(req);
            //} else if (req.status >= 300) {
                // this is a redirect
            //    ERDAS.catalog.misc.callHTTP(req.getResponseHeader("Location"), "GET", null, callback, errorCallback, accept);
            } else {
                // success (or redirect?)
                ERDAS.catalog.UI.getInstance().showProgress(false);
                if (callback) callback(req);
            }
    };

    ERDAS.catalog.UI.getInstance().showProgress(true);

    req.open(method, url, true);

    if (accept) req.setRequestHeader('Accept', accept);

    if (bodyType) req.setRequestHeader('Content-Type', bodyType);

    if (body)
        req.send(body);
    else
        req.send("");
};

ERDAS.catalog.misc.DEFAULT_ERROR_CALLBACK = function(req)
{
    var conf = confirm ("An error occured (" + req.statusText + ").  " +
                        "Do you want to see the complete error message?");

    if (conf) {
        var win = window.open ("", "Error message",
                'scrollbars=1,resizable=1,menubar=0');
        win.document.documentElement.innerHTML = req.responseText;
    }
};

function XMLHTTPObject() {
    var xmlhttp = false;

    //If XMLHTTPRequest is available
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    } else if(window.ActiveXObject) {
        //Use IE's ActiveX items
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } else  {
        xmlhttp = false; //Browser don't support Ajax
    }

    return xmlhttp;
}

ERDAS.catalog.misc.setClass = function (element, className, active) {
    var isCurrentlyActive = ERDAS.catalog.misc.isClassActive(element, className);
    if (isCurrentlyActive && !active) {
        element.className = element.className.replace(className, "");
    } else if (!isCurrentlyActive && active) {
        element.className += ' '+className;
    }
}

ERDAS.catalog.misc.isClassActive = function (element, className) {
    return element && element.className && element.className.indexOf(className)>=0;
}


ERDAS.catalog.misc.registerEventHandler = function(obj, eventName, handler, override)
{
    if (override) {
        this.unregisterEventHandler(obj, eventName);
    }

    if (!obj.addEventListener) obj.attachEvent('on' + eventName, handler);
    else obj.addEventListener(eventName, handler, true);

    obj.onloadHandler = handler;
}

ERDAS.catalog.misc.unregisterEventHandler = function(obj, eventName)
{
    if (obj && obj.onloadHandler) {
        if (!obj.removeEventListener) obj.detachEvent('on' + eventName, obj.onloadHandler);
        else obj.removeEventListener(eventName, obj.onloadHandler, true);

        obj.onloadHandler = null;
    }
}

function toggleVisibility(elem) {
    if (elem.style.display == 'none') elem.style.display = 'block';
    else elem.style.display = 'none';
}

function modifyCssClass(className, attrName, attrValue) {
    var cssRules;
    if (document.all) cssRules = 'rules';
    else if (document.getElementById) cssRules = 'cssRules';

    for (var S = 0; S < document.styleSheets.length; S++) {
        for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) {
            if (document.styleSheets[S][cssRules][R].selectorText == className) {
                document.styleSheets[S][cssRules][R].style[attrName] = attrValue;
            }
        }
    }
}

