/*
    layers.js
    -This file will handle layer interaction with kernel
    -it will handle events to show/hide layers
    -it will also abstract WMS and tilecache as well as other schemes

*/


/* 
    Map should have an instance of LayerList     
*/
function LayerList(map)
{
    that = this;
    this.layers = new LayerCollection();
    this.groups = new GroupCollection();
    this.folders = new FolderCollection();
    this.domlist = document.getElementById('layers');
    
    this.init = function(file)
    {
        var xhr = newXHR();
        xhr.open("POST",file,false);
        xhr.send(null);
	    var xml = xhr.responseXML;
	    var layerstag = xml.getElementsByTagName("layers")[0];
	    this.parse(layerstag);
    }
    
    
    //parse the layer config
    this.parse = function(xml)
	{
		for(var i=0;i<xml.childNodes.length;i++)
		{
			var xmlObj = xml.childNodes.item(i);
			if(xmlObj.tagName=="group")
			{
			    that.parseGroup(xmlObj, name, that.domlist);			
			}
			else if(xmlObj.tagName=="folder")
			{
				that.parseFolder(xmlObj, 0, that.domlist);
			}	
			else if(xmlObj.tagName=="layer")
			{
    			that.parseLayer(xmlObj,0,0, that.domlist);
			}
			
		}
	}
	
	//parse a layer out of the xml config
    this.parseLayer = function(xml,folder,group,domroot)
    {
        var service = xml.getAttribute('service');
		var name = xml.getAttribute('name');
		var title = xml.getAttribute('title');
		var display = xml.getAttribute('display');
		var enabled = true;	
		
		
		var minscale = null;
		var maxscale = null;
		try {minscale = xml.getAttribute('minscale');}catch(e){}
		try {maxscale = xml.getAttribute('maxscale');}catch(e){}			
		
		
		var l = new Layer(service,name,title,display,enabled,minscale,maxscale,folder.name,group.name);
		//add l to map's layer collection
		that.layers.addLayer(l);
		
		if(group != 0)
		{
		    group.addLayer(l);
		}
		else
		{
		    var li = document.createElement("div");
			var ck = document.createElement("input");
			ck.setAttribute('id', 'lck_'+name);
            ck.setAttribute('type','checkbox');
			ck.setAttribute('class','check');
			li.setAttribute('id','l_'+name);
			li.className = "l_vis";
			var img = document.createElement("div");
			li.appendChild(ck);
			li.appendChild(img);
			li.appendChild(document.createTextNode(" " + title));
			domroot.appendChild(li);
			
            document.getElementById('lck_' + name).checked = display;

			function _l()
			{						
				var target = document.getElementById('l_'+name);
				_Event.addDOMEvent(target,"click",function()
                {
                    that.lClick(target,'l_'+name);
                });
			}		
			_l();

            var updateextent = function()
            {
                //this is map object
                //that is layerlist object
                var res = this.getResolution();
                var scale = OpenLayers.Util.getScaleFromResolution(res, "m");
                //scale = res * 2525.25; //this is magic scalehint number used by ArcGIS
                var oldenabled = l.enabled;
                l.inscale(scale);
                ldiv = document.getElementById('l_'+name);
                lck = document.getElementById('lck_'+name);
                if(l.enabled)
                {
                    ldiv.className = "l_vis";
                    lck.checked = l.display;
                    lck.disabled = false;
                    
                }
                else
                {
                    ldiv.className = "l_vis_dis";
                    lck.checked = false;
                    lck.disabled = true;
                }
                if(oldenabled != l.enabled)
                {
                    _Event.fireCustomEvent(this, "layerupdate");
                }
                if(this.zoom == 5)
                {
                    document.getElementById('maxZoom').innerHTML = "Max Zoom Level Reached";
                }
                else
                {
                    document.getElementById('maxZoom').innerHTML = "";
                }
            }
            map.events.register("moveend", map, updateextent);

		}
		
		
		
    }
    //parse a group out of the layer config
    //still need to code enabling code + min/max
    this.parseGroup = function(xml,folder, domroot)
    {
        var name = xml.getAttribute('name');
	    var display = xml.getAttribute('display');
	    var enabled = true;

        var minscale = null;
        var maxscale = null;
        try {minscale = xmlObj.getAttribute('minscale');}catch(e){}
        try {maxscale = xmlObj.getAttribute('maxscale');}catch(e){}


	    //create Group object and add to groupcollection
	    g = new Group(name, display, enabled, minscale, maxscale);
	    that.groups.addGroup(g);
	    
	    var li = document.createElement("div");
		var ck = document.createElement("input");
        ck.setAttribute('id','gck_'+name);
		ck.setAttribute('type','checkbox');
		ck.setAttribute('class','check');
		li.setAttribute('id','g_'+name);
		li.appendChild(ck);
		if(display=="true")
		{
			ck.checked = true;
		}
		else
		{
		    ck.checked = false;
		}
		li.className = "l_vis";
		var img = document.createElement("div");
		//img.setAttribute('src','images/map.png');
		li.appendChild(img);
		li.appendChild(document.createTextNode(" " + name));
		domroot.appendChild(li);
	    function _g()
		{
			var target = document.getElementById('g_'+name);
			_Event.addDOMEvent(target,"click",function(){that.gClick(target,"g_"+name);});
		}
		_g();

        var updateextent = function()
        {
            //this is map object
            //that is layerlist object
            var res = this.getResolution();
            var scale = OpenLayers.Util.getScaleFromResolution(res, "m");
            //scale = res * 2525.25; //this is magic scalehint number used by ArcGIS
            var oldenabled = g.enabled;
            g.inscale(scale);
            gdiv = document.getElementById('g_'+name);
            gck = document.getElementById('gck_'+name);
            if(g.enabled)
            {
                gdiv.className = "l_vis";
                gck.checked = g.display;
                gck.disabled = false;
            }
            else
            {
                gdiv.className = "l_vis_dis";
                gck.checked = false;
                gck.disabled = true;
            }
            if(oldenabled != g.enabled)
            {
                _Event.fireCustomEvent(this, "layerupdate");
            }
        }
        map.events.register("moveend", map, updateextent);

	    
	    
        for(var i=0;i<xml.childNodes.length;i++)
		{
    		var xmlObj = xml.childNodes.item(i);
	
		    if(xmlObj.tagName=="layer")
		    {
		        that.parseLayer(xmlObj,folder,g, li);
		    }
		}
    }
    //parse a folder out of the layer config
    this.parseFolder = function(xml,group,domroot)
    {
        var name = xml.getAttribute('name');
		var open = xml.getAttribute('open');
		//create Folder object and add to foldercollection
		f = new Folder(name, open);
	    that.folders.addFolder(f);
	    
	        var id = 'f_'+name;
		var clickable = document.createElement('div');
		clickable.setAttribute('id','click_' + id);
		var folderObj = document.createElement('div');	
		folderObj.setAttribute('id',id);
		var img = document.createElement("div");
		img.setAttribute('id','img_'+id);
		if(open=="true")
		{
			folderObj.className = "f_open";
			img.className = "img_f_open";
			//img.setAttribute('src','images/folder_add.png');
		}
		else
		{
			folderObj.className = "f_closed";
			img.className = "img_f_closed";
			//img.setAttribute('src','images/folder_delete.png');
		}
		clickable.appendChild(img);
		clickable.appendChild(document.createTextNode(" " + name));
		folderObj.appendChild(clickable);
		var fold = document.createElement("div");
		fold.setAttribute('id','fold_'+id);
		fold.className = (open=="true")?"l_open":"l_closed";
		folderObj.appendChild(fold);								
		domroot.appendChild(folderObj);
	    function _f()
		{
			var target = document.getElementById('click_'+id);
			_Event.addDOMEvent(target,"click",function(){that.fClick(target,id);});
		}
		_f();
	    
	    
        for(var i=0;i<xml.childNodes.length;i++)
		{
    		var xmlObj = xml.childNodes.item(i);
            
            if(xmlObj.tagName=="layer")
    	    {
    	        that.parseLayer(xmlObj,f,group, fold);
    	    }
    	    else if(xmlObj.tagName=="group")
    	    {
    	        that.parseGroup(xmlObj,f, fold);
    	    }
    	}
    }
    
    
    this.fClick = function(ref,id)
    {
    	var folder = document.getElementById(id);
    	var fold = document.getElementById('fold_'+id);
    	var img = document.getElementById('img_'+id);
    	
    	/*for(var i=0;i<folder.childNodes.length;i++)
    	{
    		var xmlobj = folder.childNodes.item(i);
    		try
    		{
    			if(xmlobj.getAttribute('id') == "fold")
    			{
    				fold = xmlobj;
    			}
    		}catch(e){}
    	}*/
    	if(folder.className=="f_open")
    	{
    		//img.setAttribute('src','images/folder_delete.png');
    		folder.className="f_closed";
    		fold.className="l_closed";
    		img.className = "img_f_closed";
    	}
    	else if(folder.className=="f_closed")
    	{
    		//img.setAttribute('src','images/folder_add.png');
    		folder.className="f_open";
    		fold.className="l_open";
    		img.className = "img_f_open";
    	}
    	
    }
    this.lClick = function(ref,id)
    {
        id = id.split("_")[1];
    	var theLayer = that.layers.getLayerById(id);
    	if(!theLayer.enabled)return;
    	var ckbox = ref.childNodes.item(0);
    	theLayer.toggle();
    	ckbox.checked = theLayer.display;
    }
    this.gClick = function(ref,id)
    {
    	id = id.split("_")[1];
    	var theGroup = that.groups.getGroup(id);
    	if(!theGroup.enabled)return;
    	var ckbox = ref.childNodes.item(0);
    	theGroup.toggle();
    }
    
}

function LayerCollection()
{
    this.layer_collection = new Array();

    this.addLayer = function(layer)
    {
        this.layer_collection.push(layer);
    }
    
    this.getLayers = function()
    {
        return this.layer_collection;
    }
    
    //return an array of Layer objects belonging to service name
    this.getLayersByService = function(service)
    {
        var tempcollect = new LayerCollection()
        for(var i=0; i < this.layer_collection.length; i++)
        {
            if(this.layer_collection[i].service == service)
            {
                t = this.layer_collection[i];
                tempcollect.addLayer(t);
            }
        }
        return tempcollect;
    }
    
    this.getLayerById = function(name)
    {
        for(var i=0; i < this.layer_collection.length; i++)
        {
            if(this.layer_collection[i].name == name)
            {
                return this.layer_collection[i];
            }
        }
    }
    
    this.getLayerString = function()
    {
        var layerstring = "";
        var ll = this.layer_collection.length;
        //counts down, layer precedence in WMS is "opposite" of how we list them
        for(var i = ll - 1; i >= 0 ; i--)
        {
            if(this.layer_collection[i].display)
            {
                layerstring += this.layer_collection[i].name + ",";
            }
        }
        layerstring = layerstring.substring(0, layerstring.length - 1);
        return layerstring;
    }
}

function GroupCollection()
{
    this.group_collection = new Array();
    
    this.addGroup = function(group)
    {
        this.group_collection.push(group);
    }
    
    //return Group object by name
    this.getGroup = function(name)
    {
        for(var i=0; i < this.group_collection.length; i++)
        {
            if(this.group_collection[i].name == name)
            {
                return this.group_collection[i];
            }
        }
    }
}

function FolderCollection()
{
    this.folder_collection = new Array();
    
    this.addFolder = function(group)
    {
        this.folder_collection.push(group);
    }
    
    //return Folder object by name
    this.getFolder = function(name)
    {
        for(var i=0; i < this.folder_collection.length; i++)
        {
            if(this.folder_collection[i].name == name)
            {
                return this.folder_collection[i];
            }
        }
    }
}

/*
    Layer object
    service: code to seperate different kinds of layers, example could be WMS or even more specific like FNAI_WMS
    name: the name of the layer for interaction with the service of the layer (eg. this will be sent to WMS)
    title: a display name
    display: boolean keeping track of weather to display the layer or not
    toggle(): turns a layer on or off
*/
function Layer(service, name, title, display, enabled, minscale, maxscale, folder, group)
{
    this.service = service;
    this.name = name;
    this.title = title;
    this.minscale = minscale;
    this.maxscale = maxscale;
    this.enabled = enabled;
    this.folder = folder;
    this.group = group;
    
    display = display=="true"?true:false;
    this.display = display;
    this.toggle = function(){  
        this.display = !this.display;
        _Event.fireCustomEvent(this, "layerupdate");
    }

    this.off = function(){
        this.display = false;
        _Event.fireCustomEvent(this, "layerupdate");
    }

    this.inscale = function(scale)
    {
        if(minscale == null || maxscale == null)
        {
            this.enabled = true;
            return true;
        }
        if(this.minscale < scale && scale < this.maxscale)
        {
            this.enabled = true;
            return true;
        }
        else
        {
            this.enabled = false;
            return false;
        }

    }
}

/*
    Group object, has an array of layer objects that belong to it
*/
function Group(name, display, enabled, minscale, maxscale)
{
    this.name = name;
    this.display = display;
    this.enabled = enabled;
    this.layers = new Array();
    
    this.addLayer = function(layer)
    {
        this.layers.push(layer);
    }
    
    this.toggle = function()
    {
        this.display = !this.display;
        var i;
        for(i = 0; i < this.layers.length - 1; i++)
        {
            this.layers[i].display = !this.layers[i].display;
            //this.layers[i].toggle();
        }
        this.layers[i].toggle();
    }

    this.off = function()
    {
        this.display = false;
        for(i = 0; i < this.layers.length - 1; i++)
        {
            this.layers[i].display = false;
        }
        this.layers[i].off();   //so we don't fire the layerupdate event for each layer
    }

    this.inscale = function(scale)
    {
        if(minscale == null || maxscale == null)
        {
            this.enabled = true;
            return true;
        }
        if(this.minscale < scale && scale < this.maxscale)
        {
            this.enabled = true;
            return true;
        }
        else
        {
            this.enabled = false;
            this.off();
            return false;
        }

    }
}

function Folder(name, open)
{
    this.name = name;
    this.open = open;
}


function FilterBox(wms)
{
    var that = this
    this.WMS = wms
    this.domroot = document.getElementById('filter');
    this.init = function(name, title, param)
    {
        this.name = name;
        this.title = title;
        this.param = param;
        
        var filter = document.createElement("div");
    	var input = document.createElement("input");
    	input.setAttribute('id','filter_input_'+name);
    	input.setAttribute('type','text');
    	filter.setAttribute('id','filter_'+name);
    	filter.setAttribute('name','filter_'+name);
    	var button = document.createElement("input");
    	button.setAttribute('type','button');
    	button.setAttribute('id','filter_button');
    	button.setAttribute('value','filter!');

    	filter.appendChild(document.createTextNode("Filter " + title + " with the " + param + " parameter"));
    	filter.appendChild(document.createElement("br"));
    	filter.appendChild(input);
    	filter.appendChild(document.createElement("br"));
    	filter.appendChild(button);
    	this.domroot.appendChild(filter);
    	
    	function _f()
		{
			var target = document.getElementById('filter_button');
			_Event.addDOMEvent(target,"click",function(){that.filterLayer();});
		}
		_f();
		
		this.layer = new Layer('hermes', name, title, true, true, 0, 0)
		this.WMS.addLayer(this.layer);
    }
    
    this.filterLayer = function()
    {
        var input = document.getElementById('filter_input_'+this.name);
        this.WMS.setFilter(this.param,input.value);
        _Event.fireCustomEvent(this.layer, "layerupdate");
        
    }
}
function addLayer(layer,name,title,display)
{
    var domroot = document.getElementById("layers");
    var li = document.createElement("div");
    var ck = document.createElement("input");
    ck.setAttribute('id', 'lck_'+name);
    ck.setAttribute('type','checkbox');
    ck.setAttribute('class','check');
    li.setAttribute('id','l_'+name);
    li.className = "l_vis";
    var img = document.createElement("div");
    li.appendChild(ck);
    li.appendChild(img);

    li.appendChild(document.createTextNode(" " + title));
    domroot.appendChild(li);

    layer.setVisibility(display)
    document.getElementById('lck_' + name).checked = display;
    function _l()
    {
        var target = document.getElementById('l_'+name);
        _Event.addDOMEvent(target,"click",function()
            {
                layer.setVisibility(!layer.getVisibility())
                var lck =  document.getElementById('lck_' + name);
                lck.checked = layer.getVisibility();
            });
    }
    _l();
}
