if (typeof Mtco == 'undefined') {
    window.Mtco = function(){};
};

if (typeof Mtco.Layer == 'undefined') {
    Mtco.Layer = function(){};
};

if (typeof Mtco.Layer.Viaah == 'undefined') {
    Mtco.Layer.Viaah = function(){};
};

if (typeof Mtco.Viaah == 'undefined') {
    Mtco.Viaah = function(){};
};

if (typeof Mtco.Control == 'undefined') {
    Mtco.Control = function(){};
};

if (typeof Mtco.Util == 'undefined') {
    Mtco.Util = {};
};


Mtco.Server = 'http://www.gis-hosting.lu';


/*
 * from https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited
 */
Mtco.Util.inherit = function(child, parent) {
    
    for (var property in parent.prototype) { 
        if (typeof child.prototype[property] == 'undefined') {
            child.prototype[property] = parent.prototype[property];
        }
    }
    return child;
}


/*
 * toggle the visibility for the layer
 */
Mtco.Control.ToggleLayer = function(map, layerName) {
    var layer;
    for(var i=0, len=map.layers.length; i<len; i++) {
        if (map.layers[i].name == layerName) {
            layer = map.layers[i];
            if (layer.visibility) {
                layer.setVisibility(false);
            } else {
                layer.setVisibility(true);
            }
            break;
        }
    }
    
    return map;
}


/*
 * Popups für Pois
 */
Mtco.Control.Popup = function(feature) {
    var map = feature.layer.map;
    var popupContent = '<div id="MtcoPopupDiv"></div>';
    
    var popup = new OpenLayers.Popup(
        'MtcoPopup',
        new OpenLayers.LonLat(
            feature.geometry.x,
            feature.geometry.y
        ),
        null,
        popupContent
    );
    //popup.autoSize = true;
    popup.closeOnMove = false;
    popup.panMapIfOutOfView = true;
    map.addPopup(popup, true);
    return popup;
}

/*
 * Click control
 * pass { onClick:function(event){ func(event){} }
 * to define event Handler function
 */
Mtco.Control.Click = OpenLayers.Class(
    OpenLayers.Control,
    {
        defaultHandlerOptions : {
            'single': true,
            'double': false,
            'pixelTolerance': 0,
            'stopSingle': false,
            'stopDouble': false
        },
        initialize : function(options) {
            this.handlerOptions = OpenLayers.Util.extend(
                {}, this.defaultHandlerOptions
            );
            OpenLayers.Control.prototype.initialize.apply(
                this, arguments
            );
            this.handler = new OpenLayers.Handler.Click(
                this, {
                    'click' : this.onClick
                }, this.handlerOptions
            );
        },
        onClick : null,
        onDblClick : null
    }
);


Mtco.Control.SelectFeatureClick = function(layer, func, unFunc) {
    
    return new OpenLayers.Control.SelectFeature(
        layer,
        {
            'onSelect' : func,
            'onUnselect' : unFunc,
            'hover' : false,
            'autoActivate' : true
        }
    );
}


Mtco.Control.SelectFeatureHover = function(layer, func, unFunc) {
    
    return new OpenLayers.Control.SelectFeature(
        layer,
        {
            'onSelect' : func,
            'onUnselect' : unFunc,
            'hover' : true,
            'autoActivate' : true
        }
    );
}


/*
 * Simple Viaah Zoompanel with custom Zin/Zout graphics
 */
Mtco.Control.ViaahZoomPanel = function() {
    var zoomPanel = new OpenLayers.Control.Panel(
        {'displayClass' : 'MtcoViaahZoomPanel', 'autoActivate': true}
    );
    
    zoomPanel.addControls(
        [
            new OpenLayers.Control.ZoomIn({'displayClass' : 'MtcoViaahZoomInButton'}),
            new OpenLayers.Control.ZoomOut({'displayClass' : 'MtcoViaahZoomOutButton'})
        ]
    );
    return zoomPanel;
}

Mtco.Viaah.Map = function(options) {
    var divId;
    var resolutions = [127,31.75,12.7,2.54,1.411];
    
    if (options.divId) {
        divId = options.divId;
    } else {
        divId = options;
    }
    
    /*
     * Zoom Level Anpassungen
     */
    if (options.zoomLevel) {
        resolutions = options.zoomLevel;
    }

    return new OpenLayers.Map(
        divId,
        {
            'resolutions': resolutions,
            'projection': new OpenLayers.Projection('EPSG:2169'),
            'maxExtent': new OpenLayers.Bounds(-5120,0,154624,195584),
            'restrictedExtent' : new OpenLayers.Bounds(32000,50000,120000,150000),
            'units': 'm',
            'controls': []
        }
    );
}

/*
 * Background Layer
 * TMS
 */
Mtco.Layer.Viaah.Background = function() {
    return new OpenLayers.Layer.TMS(
        'Viaah',
        [
            'http://tc1.gis-hosting.lu/ogc/tms/',
            'http://tc2.gis-hosting.lu/ogc/tms/',
            'http://tc3.gis-hosting.lu/ogc/tms/' 
        ],
        {
            'layername': 'fisalis',
            'type' : 'png',
            'serverResolutions' : [127,31.75,12.7,2.54,1.411]
        }
    );
}

/*
 * Vector
 */
Mtco.Layer.Viaah.ClickPosition = function() {
    return new OpenLayers.Layer.Vector(
        'Klickposition',
        {
            'styleMap' : new OpenLayers.StyleMap(
                {
                    'pointRadius' : 6,
                    'fillColor' : '#4bb001',
                    'fillOpacity' : 0.8,
                    'strokeColor' : '#378001',
                    'strokeWidth' : 2
                }
            )
        }
    );
}


Mtco.Layer.Viaah.RelatedData = function(query) {
    
    var defaultStyle = new OpenLayers.Style(
        {
            'pointRadius' : 4,
            'fillColor' : '#ffb001',
            'fillOpacity' : 0.5,
            'strokeColor' : '#ff8001',
            'strokeWidth' : 2,
            'strokeOpacity' : 0.5
        }
    );
    
    return new OpenLayers.Layer.Vector('RelatedData',
        {
            'styleMap' : new OpenLayers.StyleMap(
                {
                    'default' : defaultStyle
                }
            ),
            'strategies' : [
                new OpenLayers.Strategy.BBOX()
            ],
            'protocol': new OpenLayers.Protocol.HTTP(
                {
                    'url' : Mtco.Server + '/viaah/query',
                    'format' : new OpenLayers.Format.GeoJSON(),
                    'params' : { 'json' : query },
                    'readWithPOST' : true
                }
            ),
            'maxResolution' : 12.7
        }
    );
}

/*
 * Pois Cluster
 */
Mtco.Layer.Viaah.ClusterPois = function(query) {
	/*
	var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
	renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
	*/
    var defaultStyle = new OpenLayers.Style(
        {
            'pointRadius' : '${radius}',
            'fillColor' : '#ff8200',
            'fillOpacity' : 1,
            'strokeColor' : '#fff',
            'strokeWidth' : 2,
            'cursor' : 'pointer',
            'label' : '${label}',
            'labelAlign' : 'cm',
            'fontColor' : 'white',
            'fontFamily' : 'sans-serif',
            'fontSize' : '12px',
            'fontWeight' : 'bold'
            
        },
        {
            'context' : {
                'radius' : function(feature) {
                    if (feature.attributes.count > 1) {
                        return 8;
                    } else if (feature.attributes.count == 1) {
                        // check for custom num_clients attribute
                        if (feature.cluster[0].attributes.num_clients &&
                            feature.cluster[0].attributes.num_clients > 1) {
                                return 8;
                        }
                    }
                    return 6;
                },
                'label' : function(feature) {
                    if (feature.attributes.count > 1) {
                        return feature.attributes.count;
                    } else if (feature.cluster[0].attributes.num_clients &&
                               feature.cluster[0].attributes.num_clients > 1) {
                                    return feature.cluster[0].attributes.num_clients;
                    }
                    return '';
                }
            }
        }
    );
    
    return new OpenLayers.Layer.Vector('Pois',
        {
            'styleMap' : new OpenLayers.StyleMap(
                {
                    'default' : defaultStyle,
                    'select' : defaultStyle
                }
            ),
            'strategies' : [
                new OpenLayers.Strategy.Cluster(),
                new OpenLayers.Strategy.Fixed()
            ],
            'protocol': new OpenLayers.Protocol.HTTP(
                {
                    'url' : Mtco.Server + '/viaah/query',
                    'format' : new OpenLayers.Format.GeoJSON(),
                    'params' : { 'json' : query },
                    'readWithPOST' : true
                }
            ),
            'visibility' : true
        }
    );
}


/*
 * Hobo Cluster
 */
Mtco.Layer.Viaah.ClusterHobos = function(typeId, query) {
    
    var defaultStyle = new OpenLayers.Style(
        {
            'pointRadius' : 8,
            'externalGraphic' : 'http://viaah.lu/_res/hts/ht_' + typeId + '.png',
            'graphicWidth' : 16,
            'graphicHeight' : 16,
            'cursor' : 'pointer'
        }
    );
    
    return new OpenLayers.Layer.Vector('Hobo_' + typeId,
        {
            'styleMap' : new OpenLayers.StyleMap(
                {
                    'default' : defaultStyle,
                    'select' : defaultStyle
                }
            ),
            'strategies' : [
                new OpenLayers.Strategy.Cluster(),
                new OpenLayers.Strategy.BBOX()
            ],
            'protocol': new OpenLayers.Protocol.HTTP(
                {
                    'url' : Mtco.Server + '/viaah/query',
                    'format' : new OpenLayers.Format.GeoJSON(),
                    'params' : { 'json' : query },
                    'readWithPOST' : true
                }
            ),
            'visibility' : false
        }
    );
}


/*
 * Label, outside Luxembourg only
 */
Mtco.Layer.Viaah.Label = function() {
    return new OpenLayers.Layer.WMS(
            'Label',
            'http://www.gis-hosting.lu/ogc/service/fisalis',
            {
                'layers': ['label'],
                'format': 'image/png',
                'transitionEffect' : 'resize'
            }
            ,
            {
                'singleTile': true,
                'isBaseLayer': false,
                'maxResolution': 31.75
            }
        );
}

/*
 * Labels, whole area
 */
Mtco.Layer.Viaah.LabelFull = function() {
    return new OpenLayers.Layer.WMS(
            'LabelFull',
            Mtco.Server + '/ogc/service/fisalis_layout',
            {
                'layers': ['label'],
                'format': 'image/png',
                'transitionEffect' : 'resize'
            }
            ,
            {
                'singleTile': true,
                'isBaseLayer': false,
                'minResolution': 127
            }
        );
}




/*
 * url (string): URL to pass queries to
 * proxy (string): url of a proxy script to bypass same origin policy
 */
Mtco.Viaah.Loader = function(url, proxy) {
    this.url = url;
    this.proxy = proxy;
    this.statusCodes = {
        "success" : "",
        "notmodified" : "",
        "error" : "",
        "timeout" : "",
        "parsererror" : ""
    };
    this.zoomLevel = {
        'house_number' : 4,
        'street' : 3,
        'locality' : 1
    };
}

Mtco.Viaah.Loader.prototype = {
    proxy : null,
    log : false,
    queryMethod : 'POST',
    result : null,
    
    proxyUrl : function() {
        var proxyUrl = "";
        
        proxyUrl += this.proxy;
        proxyUrl += this.url;
        
        return proxyUrl;
    },
    
    /*
     * queryString (string): JSON Query String
     * func (function || string): Funktionsname oder Funktion
     * obj (object): Objekt, auf dem die Funktion ausgeführt werden soll
     * (loss of scope)
     */
    query : function(queryString, func, obj) {
        
        var recFunc, ajaxObj;
        
        if (!obj && !func) {
            recFunc = this.receive;
        }
        else if (!obj) {
            recFunc = func
        }
        else {
            recFunc = function(response, textStatus) {
                obj[func](response, textStatus)
            };
        }
        
        ajaxObj = {
                'cache' : false,
                'complete' : recFunc,
                'data' : { 'json' : queryString },
                'dataType' : 'json',
                'error' : this.error,
                'success' : this.success,
                'timeout' : 30000,
                'type' : this.queryMethod,
                'url' : this.url
            };
            
        if (this.proxy) {
            ajaxObj['url'] = this.proxyUrl();
        }
    
        jQuery.ajax(ajaxObj);
    }
    ,
    receive : function(request, textStatus) {
        if (textStatus == "success")
            this.result = jQuery.parseJSON(request.responseText);
    }
    ,
    error : function(XMLHttpRequest, textStatus, errorThrown) {
        alert("MtcoViaahAjaxError:\nStatus: "+textStatus+"\nError: "+errorThrown);
    }
};

/*
 * url (string): URL to pass queries to
 * origin (string): pois or hobos
 * layer (object): OpenLayers.Layer which holds the data
 */
Mtco.Viaah.GeoLoader = function(url, proxy, origin, layer) {
    Mtco.Viaah.Loader.apply(this, arguments);
    
    this.origin = origin;
    this.layer = layer;
}

Mtco.Viaah.GeoLoader.prototype = {
    receive : function(request, textStatus) {
        
        if (textStatus == "success") {
            var responseObj = jQuery.parseJSON(request.responseText);
            var geojsonFormat = new OpenLayers.Format.GeoJSON();
            this.layer.destroyFeatures();
            if (responseObj[this.origin]) {
                this.layer.addFeatures(geojsonFormat.read(responseObj[this.origin]));
            }
        } else {
            alert("MtcoViaahAjaxError:\nStatus: "+textStatus);
        }
    }
};

Mtco.Util.inherit(Mtco.Viaah.GeoLoader, Mtco.Viaah.Loader);


/*
 * frmFieldX (string): id des Formularfeldes für den Ostwert
 * frmFieldY (string): id des Formularfeldes für den Hochwert
 * layer (object): Layer für die Digitalisierung
 */
Mtco.Viaah.Digitiser = function(frmFieldX, frmFieldY, layer) {
    this.frmFieldX = frmFieldX;
    this.frmFieldY = frmFieldY;
    this.layer = layer;
    this.zoomLevel = {
        'house_number' : 4,
        'hobo' : 4,
        'street' : 3,
        'locality' : 2
    };
}

Mtco.Viaah.Digitiser.prototype = {
    
    origin : null,
    lon : 77000,
    lat : 77000,
    viaahType : null,
    
    /*
     * findet die Koordinaten des Klicks
     */
    setCoordinates : function(event) {
        var xy = event.object.getLonLatFromViewPortPx(event.xy);

        if (this.layer.features.length > 0) {
            this.layer.removeAllFeatures();
        }
        var geometry = new OpenLayers.Geometry.Point(xy.lon, xy.lat);
        var feature = new OpenLayers.Feature.Vector(geometry);
        this.layer.addFeatures([feature]);
        this.layer.redraw();
        this.setFrmFields(xy.lon, xy.lat);
    },
    /*
     * schreibt latitude und longitude in die Formularfelder
     */
    setFrmFields : function(x, y) {
        jQuery("#" + this.frmFieldX).val(x);
        jQuery("#" + this.frmFieldY).val(y);
    },
    /*
     * lädt einen evt. existierenden Punkt
     */
    loadExisting : function(loader, origin, viaahId, viaahType) {
        
        this.origin = origin;
        this.viaahType = viaahType;
        
        var queryStr = '{"method":"GET", "points":{"<<origin>>":{"items":[{"type":"<<type>>","viaah_id":<<viaah_id>>}]}}}';
        queryStr = queryStr.replace("<<origin>>", this.origin);
        queryStr = queryStr.replace("<<type>>", this.viaahType);
        queryStr = queryStr.replace("<<viaah_id>>", viaahId);
        
        loader.query(queryStr, 'receive', this);
    },
    /*
     * Empfängt die Antwort von der Datenbank
     */
    receive : function(request) {
        if (request) {
            var result = jQuery.parseJSON(request.responseText);
            
            if (result && result['status'] != 'OK') {
                this.layer.destroyFeatures();
                
                var geojsonFormat = new OpenLayers.Format.GeoJSON();
                this.layer.addFeatures(geojsonFormat.read(result));
                
                this.lon = result['features'][0]['geometry']['coordinates'][0];
                this.lat = result['features'][0]['geometry']['coordinates'][1];
                this.setFrmFields(this.lon, this.lat);
            }
        }
        // Karte auf punkt oder default zentrieren
        this.layer.map.setCenter(
            new OpenLayers.LonLat(this.lon, this.lat),
            this.zoomLevel[this.viaahType]
        );
    }
}

