//$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/apps/igeoportal-standard/branches/2.5_testing/layerlistview.js $
/*----------------------------------------------------------------------------
 This file is part of deegree, http://deegree.org/
 Copyright (C) 2001-2009 by:
 - Department of Geography, University of Bonn -
 and
 - lat/lon GmbH -

 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free
 Software Foundation; either version 2.1 of the License, or (at your option)
 any later version.
 This library is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 details.
 You should have received a copy of the GNU Lesser General Public License
 along with this library; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 Contact information:

 lat/lon GmbH
 Aennchenstr. 19, 53177 Bonn
 Germany
 http://lat-lon.de/

 Department of Geography, University of Bonn
 Prof. Dr. Klaus Greve
 Postfach 1147, 53001 Bonn
 Germany
 http://www.geographie.uni-bonn.de/deegree/

 e-mail: info@deegree.org
----------------------------------------------------------------------------*/

/*
implementation of LayerListView where only one layer can be selected
for being target for GetFeatureInfo requests
*/
function LayerListView(modulename, layerlist, label, bgcolor, fgcolor) {

    this.modulename = modulename;
    this.lList = layerlist;
    this.label = label;
    this.ownDoc = null;
    this.ownerNode = null;
    this.bgcolor = bgcolor;
    this.fgcolor = fgcolor; // this color is used to highlight a layer when clicked on the name. it's not the text color.
    this.flag = false;
    this.selectedRow = null;

    this.getModuleName = getModuleName;
    this.paint = paint;
    this.repaint = repaint;
    this.up = up;
    this.down = down;
    this.change = change;
    this.clickRadioButton = clickRadioButton;
    this.countSelectedLayers = countSelectedLayers;
    this.getRadioButtonId = getRadioButtonId;
    this.countActiveLayers = countActiveLayers;
    this.clickCheckBox = clickCheckBox;
    this.addIMG = addIMG;
    this.addRow = addRow;
    this.addColumn = addColumn;
    this.addTable = addTable;
    this.addInput = addInput;
    this.addServiceIdentificationRow = addServiceIdentificationRow;
    this.moveRow = moveRow;
    this.getLayerGroupByRow = getLayerGroupByRow;
    this.paintLayerGroupTable = paintLayerGroupTable;
    this.paintLayer = paintLayer;
    this.removeElementById = removeElementById;
    this.getActiveLayer = getActiveLayer;
    this.getLayerList = getLayerList;
    this.resetRadioButtons = resetRadioButtons;
    this.getLayerIndexAssignedToInput = getLayerIndexAssignedToInput;
    this.getLayerGroupAssignedToInput = getLayerGroupAssignedToInput;
    this.addServiceButtons = addServiceButtons;
    // this.addImage = addImage;
    this.showMetadata = showMetadata;

    function getLayerList(){
        return this.lList;
    }

    function getModuleName() {
        return this.modulename;
    }

    function up(){
        var selectedRow = this.selectedRow;
        if(selectedRow == null)  {
            alert("Please select a layer");
        } else {
            var index = selectedRow.indexOf("r");
            var index2 = selectedRow.indexOf("c");
            var zeile = parseInt ( selectedRow.substring(index+1, index2) );
            if (zeile-1 < 0) {
                alert("Layer cannot be moved up");
            } else {
                var rowId = selectedRow.substring(0, index+1);
                var rowLG = selectedRow.substring(1, index);
                if (this.moveRow(zeile, -1, rowLG) < 0 ) {
                    alert("Layer cannot be moved up");
                } else {
                    this.change( rowId + (zeile-1));
                }
            }
        }
    }

    function getLayerGroupByRow(rowLG){
        var layerGroups = this.lList.getLayerGroups();
        return layerGroups[rowLG];
    }

    function moveRow(index, dir, rowLG){
        var layergroup = this.getLayerGroupByRow(rowLG);
        if ( index + dir > layergroup.getLayers().length -1) {
            return - 1;
        } else if ( index + dir < 0 ) {
            return - 1;
        }
        layergroup.swapLayers(index, index + dir);
        this.removeElementById("table1");
        this.removeElementById("table2");
        this.paint( this.ownDoc, this.ownerNode);
        // uncomment following statement if map and legend shall be
        // updated without pressing the refresh button
        //parent.controller.repaint();
        return 1;
    }

    function removeElementById(id){
        var node = this.ownDoc.getElementById(id);
        var pn = node.parentNode;
        pn.removeChild( node );
    }

    function down(){
        var table = this.ownDoc.getElementById("tableLayerGroups");
        var selectedRow = this.selectedRow;
        if(selectedRow == null)  {
            alert("Please select a layer.");
        } else {
            var index = selectedRow.indexOf("r");
            var index2 = selectedRow.indexOf("c");
            var zeile = parseInt(selectedRow.substring(index+1, index2) );
            var rowId = selectedRow.substring(0, index+1);
            var rowLG = selectedRow.substring(1, index);
            if (this.moveRow(zeile, 1, rowLG) < 0) {
                alert("Layer cannot be moved down.");
            } else {
                this.change( rowId + (zeile+1));
            }
        }
    }

    function showMetadata() {
        // identify selected layer
        var table = this.ownDoc.getElementById( "tableLayerGroups" );
        var selectedRow = this.selectedRow;
        if( selectedRow == null ) {
            alert( "Please choose a topic first." );
        } else {
            var index = selectedRow.indexOf( "r" );
            var index2 = selectedRow.indexOf( "c" );
            var zeile = parseInt ( selectedRow.substring( index+1, index2 ) );
            var rowLG = selectedRow.substring( 1, index );
            var layerGroup = this.getLayerGroupByRow(rowLG);
            var layer = layerGroup.getLayers()[zeile];
            var metaUrl = encodeURIComponent( layer.getMetadataURL() );

            var s = "control?rpc=<?xml version='1.0' encoding='UTF-8'?><methodCall>" +
                    "<methodName>cswClient:singleLayerSearch</methodName>" +
                    "<params><param><value><struct>" +
                        "<member><name>METADATA_URL</name><value><string><![CDATA[" + metaUrl + "]]></string></value></member>" +
                        "<member><name>METADATA_TITLE</name><value><string><![CDATA[" +layer.getTitle()+ "]]></string></value></member>" +
                        "<member><name>catalog</name><value><string>CATA1</string></value></member>" +
                    "</struct></value></param></params></methodCall>";

            // start metadata search
            window.open ( s, "title", "width=680,height=400,left=150,top=200,scrollbars=yes,resizable=yes" );
        }
    }

    function addRow( table, bgcolor, height ) {
        var tr = this.ownDoc.createElement("tr");
        if ( bgcolor != null && bgcolor != "undefined" && bgcolor != "null" && bgcolor != "" && bgcolor != "-" ) {
            tr.style.backgroundColor = bgcolor;
        }
        tr.setAttribute("height", height);
        table.appendChild(tr);
        return tr;
    }

    function addColumn( tr, bgcolor, width ) {
        var td = this.ownDoc.createElement("td");
        if ( bgcolor != null && bgcolor != "undefined" && bgcolor != "null" && bgcolor != "" && bgcolor != "-" ) {
            td.style.backgroundColor = bgcolor;
        }
        //td.setAttribute("valign", 'top'); // doesn't work in IE !!!
        td.setAttribute("align", 'left');
        td.setAttribute("width", width);
        
        var attrNode = this.ownDoc.createAttribute( "valign" );
        attrNode.nodeValue = "top";
        td.setAttributeNode( attrNode );
        
        tr.appendChild(td);
        return td;
    }

    function addTable( id, border, height, width, parentNode){
        var table = this.ownDoc.createElement("TABLE");
        var oTBody0 = this.ownDoc.createElement("TBODY");
        table.setAttribute("border", border);
        table.setAttribute("id", id);
        table.setAttribute("cellPadding", 0);
        table.setAttribute("cellSpacing", 0);
        table.setAttribute("width", width);
        if ( this.bgcolor != null && this.bgcolor != "undefined" && this.bgcolor != "null" && this.bgcolor != "" && this.bgcolor != "-" ) {
            table.style.backgroundColor = this.bgcolor;
        }
        
        table.appendChild( oTBody0 );
        parentNode.appendChild(table);
        return oTBody0;
    }

    function addServiceIdentificationRow( bgcolor, id, height, wmsName, wmsUrl, table){
        var trWMSName = this.ownDoc.createElement("tr");
        if ( bgcolor != null && bgcolor != "undefined" && bgcolor != "null" && bgcolor != "" && bgcolor != "-" ) {
        	trWMSName.style.backgroundColor = bgcolor;
        }
        trWMSName.setAttribute("id", id);
        trWMSName.setAttribute("height", height);
        trWMSName.setAttribute("name", wmsName);
        trWMSName.setAttribute("value", wmsUrl);
        table.appendChild(trWMSName);
        return trWMSName;
    }

    function addInput(id, bgcolor, type, name, width, height, td, onclick){
        var input = this.ownDoc.createElement("INPUT");
        //input.setAttribute("bgColor", bgcolor);
        input.setAttribute("type", type);
        input.setAttribute("id", id);
        input.setAttribute("name", name);
        input.setAttribute("width", width);
        input.setAttribute("height", height);
        input["onclick"]= new Function( onclick );
        td.appendChild(input);
        return input;
    }

    function addIMG( src, border, href, width, height, title ){
        var img = this.ownDoc.createElement("img");
        img.setAttribute("src", src);
        img.setAttribute("border", border);
        if ( width != null && width > 0 ) {
            img.setAttribute("width", width);
        }
        if ( height != null && height > 0 ) {
            img.setAttribute("height", height);
        }
        if ( title != null && title != "" ) {
        	img.setAttribute("title",title);
        }
        href.appendChild(img);
        return img;
    }
    
    function paint(targetDocument, parentNode) {
        this.flag = false;
        this.ownDoc = targetDocument;
        this.ownerNode = parentNode;
        //first table
        var table = this.addTable('table1', 0, 30, '97%', this.ownerNode);
        var tr = this.addRow( table, this.bgcolor, 20 );
        var td = this.addColumn( tr, this.bgcolor, 100);
        //theme
        /* build label the same way as in other modules, i.e. contextswitcher, scaleswitcher */
        /*
        var theme = this.ownDoc.createTextNode( label );
        var h = this.ownDoc.createElement("h4");
        td.appendChild(h);
        h.appendChild(theme);
        */
//        var span = targetDocument.createElement( "span" );
//        span.setAttribute( "className", "listfont" );
        var b = this.ownDoc.createElement( "b" );
        var theme = this.ownDoc.createTextNode( this.label );
        b.appendChild( theme );
//        span.appendChild( b );
//        td.appendChild( span );
        td.appendChild( b );

        //second tr
        tr = this.addRow( table, this.bgcolor, 20 );
        td = this.addColumn( tr, this.bgcolor, '97%' );
        table = this.addTable( 'tableLayerGroups', 0, 50, '97%', td );

        //layergroups
        var layerGroups = this.lList.getLayerGroups();
        for (var i = 0; i < layerGroups.length; i++){
            this.paintLayerGroupTable( table, layerGroups[i], i);
        }
        
        //table for move up/down button
        table = this.addTable('table2', 0, 20, '97%', this.ownerNode);
        tr = this.addRow(  table, this.bgcolor, 20 );
        
        //layer moves up
        td = this.addColumn(  tr, this.bgcolor, 40);
        td.setAttribute("align", 'center');
        var br = this.ownDoc.createElement("br");
        td.appendChild(br);
        var href = this.ownDoc.createElement("a");
        href.setAttribute("href","javascript:parent.controller.vLayerListView.up();");
        td.appendChild(href);
        var img = this.addIMG( './images/up.gif', 0, href, 16, 16, 'move layer up' );
        
        //layer moves down
        td = this.addColumn( tr, this.bgcolor, 40);
        td.setAttribute("align", 'center');
        br = this.ownDoc.createElement("br");
        td.appendChild(br);
        href = this.ownDoc.createElement("a");
        href.setAttribute("href","javascript:parent.controller.vLayerListView.down()");
        td.appendChild(href);
        var img = this.addIMG( './images/down.gif', 0, href, 16, 16, 'move layer down' );

        // show metadata for selected layer
        // button is only visible and active, if metadataURL is available for the selected layer.
        var table = this.ownDoc.getElementById( "tableLayerGroups" );
        var selRow = this.selectedRow;
        var mdURL = null;
        if( selRow != null && selRow != "" ) {
            var index = selRow.indexOf( "r" );
            var index2 = selRow.indexOf( "c" );
            var zeile = parseInt ( selRow.substring( index+1, index2 ) );
            var rowLG = selRow.substring( 1, index );
            var layerGroup = this.getLayerGroupByRow(rowLG);
            if ( layerGroup != null && layerGroup != "" ) {
                var layer = layerGroup.getLayers()[zeile];
                if ( layer != null ) {
                	mdURL = layer.getMetadataURL();
                }
            }
        }

        if ( parent.controller.vCswModule != null ) {
            if ( mdURL != null && mdURL != "" && mdURL != "null" ) {
                // active state - layer has metadata url
                td = this.addColumn( tr, this.bgcolor, 110);
                td.setAttribute("align", 'right');
                br = this.ownDoc.createElement("br");
                td.appendChild(br);
                href = this.ownDoc.createElement("a");
                href.setAttribute("href","javascript:parent.controller.vLayerListView.showMetadata()");
                td.appendChild(href);
                var img = this.addIMG( './images/md_info_a.gif', 0, href, 16, 16, 'show metadata');
            } else {
            	// passive state - layer does not have metadata url
                td = this.addColumn( tr, this.bgcolor, 110);
                td.setAttribute("align", 'right');
                br = this.ownDoc.createElement("br");
                td.appendChild(br);
                var img = this.addIMG( './images/md_info.gif', 0, td, 16, 16, 'no metadata available');
            }
        }
    }

    function repaint() {
        this.removeElementById("table1");
        this.removeElementById("table2");
        this.paint(this.ownDoc, this.ownerNode);
    }

    function paintLayerGroupTable(table, layerGroup, t){
        var trWMSName = this.addServiceIdentificationRow( this.bgcolor, 'Service' + t, 20,
                                                          layerGroup.serviceName,
                                                          layerGroup.serviceURL, table);

        // the following td contains the subheader above a group of layers
        var td = this.addColumn( trWMSName, this.bgcolor, '100%');
        td.appendChild(this.ownDoc.createTextNode(layerGroup.serviceName + ':'));

        this.addServiceButtons( td, layerGroup.id, t );
        var table2 = this.addTable( 'tableLayers', 0, 100, '97%', td);
        var layers = layerGroup.getLayers();
        for (var j = 0; j < layers.length; j++ ){
            this.paintLayer( table2, layers[j], j, t);
        }
    }

    function addServiceButtons( td, id, index ) {
        if ( this.lList.getLayerGroups().length > 1 ) {
            var tn = this.ownDoc.createTextNode(" ");
            td.appendChild( tn );
            var href = this.ownDoc.createElement("a");
            href.setAttribute("href","javascript:parent.controller.removeLayerGroup('" + id + "')");
            var inp = this.ownDoc.createElement("img");
            inp.setAttribute("src","./images/remove.gif");
            inp.setAttribute("border","0");
            inp.setAttribute("width","13");
            inp.setAttribute("height","13");
            inp.setAttribute("title","WMS entfernen");
            href.appendChild( inp );
            td.appendChild( href );
            tn = this.ownDoc.createTextNode(" ");
            td.appendChild( tn );

            if ( index > 0 ) {
                href = this.ownDoc.createElement("a");
                href.setAttribute("href","javascript:parent.controller.moveLayerGroupUp(" + index + ")");
                inp = this.ownDoc.createElement("img");
                inp.setAttribute("src","./images/up.gif");
                inp.setAttribute("border","0");
                inp.setAttribute("width","13");
                inp.setAttribute("height","13");
                inp.setAttribute("title","move WMS up");
                href.appendChild( inp );
                td.appendChild( href );
                var tn = this.ownDoc.createTextNode(" ");
                td.appendChild( tn );
            }

            if ( index < this.lList.getLayerGroups().length-1 ) {
                href = this.ownDoc.createElement("a");
                href.setAttribute("href","javascript:parent.controller.moveLayerGroupDown(" + index + ")");
                inp = this.ownDoc.createElement("img");
                inp.setAttribute("src","./images/down.gif");
                inp.setAttribute("border","0");
                inp.setAttribute("width","13");
                inp.setAttribute("height","13");
                inp.setAttribute("title","move WMS down");
                href.appendChild( inp );
                td.appendChild( href );
            }
        }
    }

    function paintLayer(table, layer, r, t){
        var bkgr = this.bgcolor;
        var fntColor = '#000000';
        // enable scale hint highlighting
        if ( parent.controller.mapModel.getScale() < layer.getMinScale() ||
             parent.controller.mapModel.getScale() > layer.getMaxScale() ) {
        	 bkgr = '#EEEEEE';
             fntColor = '#676767';
        }
        if ( ('t' + t + 'r' + r + 'c1') == this.selectedRow ) {
            bkgr = 'feedb6';
        }
        tr = this.addRow( table, bkgr, 10 );
        tr.setAttribute("id", "t" + t + "row" + r);
        tr.setAttribute("title", layer.getAbstract() );
        
        // checkbox column:
        td = this.addColumn( tr, bkgr, 15);
        td.setAttribute("id", "t" + t + "r" + r + "c0");
        td.setAttribute("align", 'center');
        var input = this.addInput('checkId' + t + 'r' + r, this.fgcolor, 'checkbox', 'check',
                            15, 15, td, 'parent.controller.vLayerListView.clickCheckBox(this)');
        if ( layer.isVisible() ) {
             input.checked = true;
        }
        
        // layer name column:
        td = this.addColumn( tr, bkgr, '*');
        td.setAttribute("id", "t" + t + "r" + r + "c1");
        td["onclick"]= new Function( "parent.controller.vLayerListView.change('t" + t + "r" + r + "' )" );
        td.setAttribute("style", "color:" + fntColor);
        td.appendChild( this.ownDoc.createTextNode(layer.getTitle() ) );
        
        // radio button column:
        td = this.addColumn( tr, bkgr, 15);
        if ( layer.isQueryable() ) {
            td.setAttribute("id", "t" + t + "r" + r + "c2");
            td.setAttribute("align", 'center');
            var input = this.addInput('radioId' + t + 'r' + r, this.fgcolor, 'radio', 'radiocheck',
                                 15, 15, td, 'parent.controller.vLayerListView.clickRadioButton(this)');
            if ( layer.isSelected() ) {
                layer.setSelected(true);
                input.checked = true;
            }
        }
    }

    function getLayerIndexAssignedToInput(input) {
        var i1 = input.id.lastIndexOf( 'r' );
        var i2 = input.id.length;
        return parseInt( input.id.substring(i1+1, i2) );
    }

    function getLayerGroupAssignedToInput(input) {
        var i1 = input.id.lastIndexOf( 'd' );
        var i2 = input.id.lastIndexOf( 'r' );
        var i = parseInt( input.id.substring(i1+1, i2) );
        return this.lList.getLayerGroup( i );
    }

    function clickCheckBox(p) {
        var lg = this.getLayerGroupAssignedToInput(p);
        var li = this.getLayerIndexAssignedToInput(p);
        var lg = this.getLayerGroupAssignedToInput(p);
        var layer = lg.getLayer( li );
        if (!p.checked) {
            if ( this.countSelectedLayers() > 0 ) {
                var rbId = this.getRadioButtonId( p );
                var countAL = this.countActiveLayers();
                var al = this.getActiveLayer();
                if ( al == rbId ) {
                    this.ownDoc.getElementById(rbId).firstChild.checked = false;
                    layer.setSelected( false );
                }
            } else {
                p.checked = true;
            }
        }
        lg.setChanged(true);
        layer.setVisible( p.checked );
        this.removeElementById("table1");
        this.removeElementById("table2");
        this.paint(this.ownDoc, this.ownerNode);
        // uncomment following statement if map and legend shall be
        // updated without pressing the refresh button
        //parent.controller.repaint();
    }

    function countSelectedLayers() {
        var count = 0;
        var check = this.ownDoc.getElementsByName("check");
        var lg = this.lList.getLayerGroups();
        for (var j = 0; j < lg.length; j++) {
            var layers = lg[j].getLayers();
            for (var i = 0; i < layers.length; i++) {
                var id = "checkId" + j + 'r' + i;
                var idCheck = this.ownDoc.getElementById(id);
                if( idCheck != null ){
	                if (idCheck.checked) {
	                    count++;
	                }
	            }
            }
        }
        return count;
    }

    function getActiveLayer(){
        var layerGroups = this.lList.getLayerGroups();
        for (var j = 0; j < layerGroups.length; j++){
            var layers = layerGroups[j].getLayers();
            for (var i = 0; i < layers.length; i++){
                var id = "t" + j + "r" + i + "c2";
                if ( this.ownDoc.getElementById(id) != null ) {
                    var rb = this.ownDoc.getElementById(id).firstChild.checked;
                    if (rb == true){
                        return id;
                        break;
                    }
                }
            }
        }
    }

    function getRadioButtonId (p) {
        var id = p.parentNode.id;
        var index = id.lastIndexOf('c');
        var sub = id.substring(0, index+1);
        var radioId = sub + "2";
        return radioId;
    }

    function getCheckBoxId (p) {
        var id = p.parentNode.id;
        var index = id.lastIndexOf('c');
        var sub = id.substring(0, index+1);
        var checkId = sub + "0";
        return checkId;
    }

    function countActiveLayers(){
        var count = 0;
        var lg = this.lList.getLayerGroups();
        for (var j = 0; j < lg.length; j++){
            var layers = lg[j].getLayers();
            for (var i = 0; i < layers.length; i++){
                var id = "radioId" + j + 'r' + i;
                var idCheck = this.ownDoc.getElementById(id);
                if ( idCheck != null ) {
                    var lay = idCheck.checked;
                    if (lay == true) {
                        count++;
                    }
                }
            }
        }
        return count;
    }

    function resetRadioButtons() {
        var layerGroups = this.lList.getLayerGroups();
        for (var j = 0; j < layerGroups.length; j++){
            var layers = layerGroups[j].getLayers();
            for (var i = 0; i < layers.length; i++){
                var id = "t" + j + "r" + i + "c2";
                if ( this.ownDoc.getElementById(id) != null ) {
                    this.ownDoc.getElementById(id).firstChild.checked = false;
                    layers[i].setSelected( false );
                }
            }
        }
    }

    function clickRadioButton(param){
        var li = this.getLayerIndexAssignedToInput(param);
        var lg = this.getLayerGroupAssignedToInput(param);
        var layer = lg.getLayer( li );
        var checkid = getCheckBoxId (param);
        this.resetRadioButtons();
        param.checked = true;
        this.ownDoc.getElementById( checkid ).firstChild.checked = true;
        layer.setChanged(true);
        layer.setSelected( param.checked );
        layer.setVisible( param.checked );
        this.repaint();
    }

    function change(rowID)  {
        if (rowID != null)  {
            this.selectedRow = rowID + "c1";
        }
        this.repaint();
    }

}
