var _url_scale="";
var _url_image="";
var _w=0;
var _h=0;
var _scale="";
var _LAYER_SELECTED="";

function Map_Wrapper()
{
    this._minx=0;
    this._maxx=0;
    this._miny=0;
    this._maxy=0;
    this._width=0;
    this._height=0;
    this._scale=0;
    this._id_map=0;
}

Map_Wrapper.prototype.update_map=function(url,url_scale,url_ref,scale,minx,maxx,miny,maxy,w,h,id_map)
{
    try{
        //Save the extent
        this._minx=parseFloat(new Number(minx));
        this._maxx=parseFloat(new Number(maxx));
        this._miny=parseFloat(new Number(miny));
        this._maxy=parseFloat(new Number(maxy));
        this._width=parseFloat(new Number(w));
        this._height=parseFloat(new Number(h));
        this._scale= new Number(scale);
        this._id_map = id_map;
        _url_scale=url_scale;
        _url_image=url;
        _w=w;
        _h=h;
        _scale=scale;
		
        //Div reference
        var div_ref = document.getElementById("reference_map");
        clear_node(div_ref);
        var img_ref =document.createElement("img");
        div_ref.appendChild(img_ref);

        img_ref.style.top="0px";
        img_ref.style.left="0px";
        img_ref.style.width="100px";
        img_ref.style.height="95px";
        img_ref.onload= function(){
            loaded_ref();
        }
        img_ref.src=url_ref;
		
    }catch(e)
    {
        alert("Map_Wrapper.update_map(): "+e);
        return false;
    }
	
};
Map_Wrapper.prototype.convert_to_geo=function(x,y)
{
    var x_pct = x /this._width;
    var y_pct = 1-(y /this._height );
    var x_map =  this._minx + ( (this._maxx - this._minx  )*x_pct)  ;
    var y_map =  this._miny + ( (this._maxy -this._miny ) *y_pct) ;
    if(_COORDINATE_PRECISION != 0){
        return new Array(parseFloat( new Number(x_map).toFixed(_COORDINATE_PRECISION) ),
            (new Number(y_map ).toFixed(_COORDINATE_PRECISION)) );
    }else{
        return new Array(parseFloat( new Number(x_map) ), (new Number(y_map )) );

    }
};

Map_Wrapper.prototype.convert_to_pixel=function(x,y,inv)
{
    x = parseFloat(x);
    y = parseFloat(y);
    var x_pxl=(  (x-this._minx)*this._width )/ (this._maxx-this._minx);
    var y_pxl=(  (y-this._miny)*this._height )/(this._maxy-this._miny);
    y_pxl=inv ? this._height-y_pxl : y_pxl;
    return new Array(x_pxl,y_pxl);
};

Map_Wrapper.prototype.convert_point_to_pixel=function(point,inv)
{
    var pxl = this.convert_to_pixel(point._x,point._y,inv);
    return new Point(pxl[0],pxl[1]);
};


Map_Wrapper.prototype.convert_point_to_geo=function(point)
{
    var geo = this.convert_to_geo(point._x,point._y);
    return new Point(geo[0],geo[1]);
};


Map_Wrapper.prototype.clear_map=function()
{
    clear_node(document.getElementById(_MAP_ID));
};

Map_Wrapper.prototype.convert_to_absolute_screen_coords=function(x,y)
{
	
    var offset_left=document.getElementById(_WINDOW_ID).offsetLeft+
    document.getElementById(_MAP_ID).offsetLeft;
	
    var offset_top=document.getElementById(_WINDOW_ID).offsetTop
    +document.getElementById(_MAP_ID).offsetTop;
	
    return new Array(x+offset_left,y+offset_top);
};

Map_Wrapper.prototype.convert_to_relative_pixel_coords=function(x,y)
{
    var offset_left = document.getElementById(_WINDOW_ID).offsetLeft
    +document.getElementById(_MAP_ID).offsetLeft;
	
    var offset_top=document.getElementById(_WINDOW_ID).offsetTop+
    document.getElementById(_MAP_ID).offsetTop;
	
    var r_x=0;
    var r_y=0;
	
    var scrOfY=0;
    var scrOfX=0;
	
    if( typeof( window.pageYOffset ) == 'number' ) {
        //Netscape compliant
        scrOfY = window.pageYOffset;
        scrOfX = window.pageXOffset;
    } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
        //DOM compliant
        scrOfY = document.body.scrollTop;
        scrOfX = document.body.scrollLeft;
    } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
        //IE6 standards compliant mode
        scrOfY = document.documentElement.scrollTop;
        scrOfX = document.documentElement.scrollLeft;
    }
	
    r_x=x+scrOfX-offset_left;
    r_y=y+scrOfY-offset_top;
	
    return new Array(r_x,r_y);
	
};
Map_Wrapper.prototype.evt_select_layer = function(layer_div)
{
    if(_LAYER_SELECTED == layer_div.id)
    {
        layer_div.className="layer";
        _LAYER_SELECTED = "";
        return;
    }
    else if(_LAYER_SELECTED != layer_div.id && _LAYER_SELECTED != "" 
        && document.getElementById(_LAYER_SELECTED) != null )
        {
        document.getElementById(_LAYER_SELECTED).className="layer";
        _LAYER_SELECTED = "";
	
    }
	
    _LAYER_SELECTED=layer_div.id;
    layer_div.className="layer_selected";
};

Map_Wrapper.prototype.is_layer_selected=function(layer_name)
{

    if(_LAYER_SELECTED == layer_name)
        return true;
    else
        return false;
};

Map_Wrapper.prototype.deg_to_rad=function(deg)
{
    return deg*Math.PI/180;
};
Map_Wrapper.prototype.rad_to_deg=function(rad)
{
    return rad*180/Math.PI;
};

Map_Wrapper.prototype.calculate_circle_point_from_2_points = function(p1,p2,radius)
{
    var q = p1.distance(p2);
    var midle_point = new Point( (p1._x+p2._x)/2,(p1._y+p2._y)/2 );
    var x=0,y=0;
	
    if(radius > 0)
    {
        x = midle_point._x+Math.sqrt( Math.pow(radius,2)-Math.pow(q/2,2) ) * (p1._y-p2._y)/q;
        y = midle_point._y+Math.sqrt( Math.pow(radius,2)-Math.pow(q/2,2) ) * (p2._x-p1._x)/q;
    }
    else
    {
        x = midle_point._x-Math.sqrt( Math.pow(Math.abs(radius),2)-Math.pow(q/2,2) ) * (p1._y-p2._y)/q;
        y = midle_point._y-Math.sqrt( Math.pow(Math.abs(radius),2)-Math.pow(q/2,2) ) * (p2._x-p1._x)/q;
    }
 	

    var center = new Point(x,y);
    if(isNaN(center._x) || isNaN(center._y)){
        throw _MSG_RADIUS_NOT_VALID;
    }
 	
    midle_point= new Point((p1._x+p2._x)/2,(p1._y+p2._y)/2);
    var p = new Point(1,0);
    p._x=p._x*Math.abs(radius);
    p._y=p._y*Math.abs(radius);
    p._x=p._x+center._x;
    p._y=p._y+center._y;
	
    var ref_vector = new Array(p._x-center._x,p._y-center._y);	
    var v3 = new Array(midle_point._x-center._x,midle_point._y-center._y);
	
    var midle_point_angle =parseInt( _MAP_WRAPPER.rad_to_deg( 
        _GENERIC_GIS_UTILS.vectors_angle(ref_vector,v3 ) ) );
	
    if(v3[1]<0)
        midle_point_angle = 360-midle_point_angle;
		
		
    var new_point = new Point(Math.cos(_MAP_WRAPPER.deg_to_rad(midle_point_angle)),
        Math.sin(_MAP_WRAPPER.deg_to_rad(midle_point_angle)));
    new_point._x=new_point._x*Math.abs(radius);
    new_point._y=new_point._y*Math.abs(radius);
    new_point._x=new_point._x+center._x;
    new_point._y=new_point._y+center._y;
	
    return new_point;
};

/*Deco an xml multicurve to the object Line_Path, every compound curve is a Line_Path Object, segments
 *and island are on the same level*/
Map_Wrapper.prototype.decode_multi_curve_from_xml = function(xml_multi_curve)
{
    var multi_curve = new Line_Path();
    multi_curve._type = "MULTICURVE";
    var xml_compound_curve = xml_multi_curve.getElementsByTagName("compound_curve");
    var id_geometry = xml_multi_curve.getElementsByTagName("id_geometry")[0].hasChildNodes() ?
    xml_multi_curve.getElementsByTagName("id_geometry")[0].firstChild.nodeValue : "";
    multi_curve._id_geometry = id_geometry;
    
    for(var j=0; j<xml_compound_curve.length;j++){
        var compound_curve = xml_compound_curve[j];
        var line_path = new Line_Path();

        for(var i=0;i<compound_curve.childNodes.length;i++)
        {
            var elem = compound_curve.childNodes[i];
            if(elem.nodeName == "arc" )
            {
                var p1 = new Point(elem.getElementsByTagName("point")[0].childNodes[0].firstChild.nodeValue,
                    elem.getElementsByTagName("point")[0].childNodes[1].firstChild.nodeValue);
                var p2 = new Point(elem.getElementsByTagName("point")[1].childNodes[0].firstChild.nodeValue,
                    elem.getElementsByTagName("point")[1].childNodes[1].firstChild.nodeValue);
                var p3 = new Point(elem.getElementsByTagName("point")[2].childNodes[0].firstChild.nodeValue,
                    elem.getElementsByTagName("point")[2].childNodes[1].firstChild.nodeValue);
                var arc = new Arc(p1,p2,p3);
                arc._optimized_drawing=true;
                arc._id_geometry = id_geometry;
                line_path.add_graphics( arc);

            }
            if(elem.nodeName == "linestring" )
            {
                var p1=null;
                var p2=null;
                var line = null;

                var list_of_points = elem.getElementsByTagName("point");
                for(var ii = 0; ii<list_of_points.length; ii++){
                    if(ii+1 ==list_of_points.length ){
                        break;
                    }
                    
                    p1 = new Point(elem.getElementsByTagName("point")[ii].childNodes[0].firstChild.nodeValue,
                        elem.getElementsByTagName("point")[ii].childNodes[1].firstChild.nodeValue);
                    p2 = new Point(elem.getElementsByTagName("point")[(ii+1)].childNodes[0].firstChild.nodeValue,
                        elem.getElementsByTagName("point")[(ii+1)].childNodes[1].firstChild.nodeValue);
                    line = new Line(p1,p2) ;
                    line._optimized_drawing=true;
                    line._id_geometry = id_geometry;
                    line_path.add_graphics( line);
                }
            }
        }

        multi_curve.add_graphics(line_path)

    }

    //normalize linepath
    var merge_linepaths = false;
    var i=0;
    while(true){
        if(i+1 == multi_curve._list_of_graphics.length){
            break;
        }

        var line_path = multi_curve._list_of_graphics[i];
        var line_path_forrward = multi_curve._list_of_graphics[i+1];
        
        merge_linepaths = false;
        
        var current_object = line_path._list_of_graphics[ line_path._list_of_graphics.length-1];
        var forrward_object =line_path_forrward._list_of_graphics[0];
        
        if(current_object instanceof Line){
            if(forrward_object instanceof Line){
                if(current_object.equals( forrward_object ) ){
                    //merge line_paths
                    merge_linepaths = true;
                }
            }else if(forrward_object instanceof Arc){
                if(current_object._p1.equals(forrward_object._p1) || current_object._p1.equals(forrward_object._p3)
                || current_object._p2.equals(forrward_object._p1)|| current_object._p2.equals(forrward_object._p3)){
                    //merge line_paths
                    merge_linepaths = true;
                }
            }
        }else if(current_object instanceof Arc){
            if(forrward_object instanceof Line){
                if(current_object._p1.equals(forrward_object._p1) || current_object._p1.equals(forrward_object._p2)
                || current_object._p3.equals(forrward_object._p1)|| current_object._p3.equals(forrward_object._p2)){
                    //merge line_paths
                    merge_linepaths = true;
                }

            }else if(forrward_object instanceof Arc){
                if(current_object._p1.equals(forrward_object._p1) || current_object._p1.equals(forrward_object._p3)
                || current_object._p3.equals(forrward_object._p1)|| current_object._p3.equals(forrward_object._p3)){
                    //merge line_paths
                    merge_linepaths = true;

                }
            }

        }
        if(merge_linepaths){
          line_path._list_of_graphics = line_path._list_of_graphics.concat(line_path_forrward._list_of_graphics);
          multi_curve._list_of_graphics.splice(i+1,1);
          i=0;
        }else{
            i++;
        }
    }

    return multi_curve;

};

Map_Wrapper.prototype.decode_multi_surface_from_xml = function(xml_multi_curve)
{
    var multi_surface = new Line_Path();
    var list_of_curve_polygons = xml_multi_curve.getElementsByTagName("curve_polygon");
    var id_geometry = xml_multi_curve.getElementsByTagName("id_geometry")[0].hasChildNodes() ?
    xml_multi_curve.getElementsByTagName("id_geometry")[0].firstChild.nodeValue : "";
    multi_surface._id_geometry=id_geometry;
    multi_surface._type="MULTISURFACE";

    for(var i=0; i<list_of_curve_polygons.length;i++){
        var xml_curve_polygon = list_of_curve_polygons[i];

        //add exterior ring
        var curve_polygon = this.decode_compound_curve_from_xml(xml_curve_polygon.getElementsByTagName("exterior_ring")[0].
            getElementsByTagName("compound_curve")[0]);

        //decode interior rings
        var list_of_intr_rings = xml_curve_polygon.getElementsByTagName("interior_ring");
        for(var j=0;j<list_of_intr_rings.length; j++){
            curve_polygon.add_graphics(this.decode_compound_curve_from_xml(list_of_intr_rings[j].
                getElementsByTagName("compound_curve")[0]));
        }
        multi_surface.add_graphics(curve_polygon);

    }
    
    return multi_surface;

};

Map_Wrapper.prototype.decode_compound_curve_from_xml = function(xml_compound_curve){
    var compound_curve = new Line_Path();
    for(var i=0;i<xml_compound_curve.childNodes.length;i++)
    {
        var elem = xml_compound_curve.childNodes[i];
        if(elem.nodeName == "arc" )
        {
            var p1 = new Point(elem.getElementsByTagName("point")[0].childNodes[0].firstChild.nodeValue,
                elem.getElementsByTagName("point")[0].childNodes[1].firstChild.nodeValue);
            var p2 = new Point(elem.getElementsByTagName("point")[1].childNodes[0].firstChild.nodeValue,
                elem.getElementsByTagName("point")[1].childNodes[1].firstChild.nodeValue);
            var p3 = new Point(elem.getElementsByTagName("point")[2].childNodes[0].firstChild.nodeValue,
                elem.getElementsByTagName("point")[2].childNodes[1].firstChild.nodeValue);
            var arc = new Arc(p1,p2,p3);
            arc._optimized_drawing=true;
            compound_curve.add_graphics( arc);

        }
        if(elem.nodeName == "linestring" )
        {
            var p1=null;
            var p2=null;
            var line = null;

            var list_of_points = elem.getElementsByTagName("point");
            for(var ii = 0; ii<list_of_points.length; ii++){
                if(ii+1 ==list_of_points.length ){
                    break;
                }

                p1 = new Point(elem.getElementsByTagName("point")[ii].childNodes[0].firstChild.nodeValue,
                    elem.getElementsByTagName("point")[ii].childNodes[1].firstChild.nodeValue);
                p2 = new Point(elem.getElementsByTagName("point")[(ii+1)].childNodes[0].firstChild.nodeValue,
                    elem.getElementsByTagName("point")[(ii+1)].childNodes[1].firstChild.nodeValue);
                line = new Line(p1,p2) ;
                line._optimized_drawing=true;
                compound_curve.add_graphics( line);
            }
        }
    }

    return compound_curve;
};

Map_Wrapper.prototype.decode_points_from_xml = function(xml_points){
    var list_of_xml_points = xml_points.getElementsByTagName("point");
    var list_of_points = new Array();
    
    for(var i=0; i<list_of_xml_points.length; i++){
        var point = new  Point( list_of_xml_points[i].getElementsByTagName("x")[0].firstChild.nodeValue,
            list_of_xml_points[i].getElementsByTagName("y")[0].firstChild.nodeValue );
        point._id_geometry=list_of_xml_points[i].getElementsByTagName("id_geometry")[0].firstChild.nodeValue;
        list_of_points.push(point);

    }
    return list_of_points;
};

Map_Wrapper.prototype.decode_linestring_from_xml = function(xml_linestring){
    var line_path = new Line_Path();
    var linestrings = xml_linestring.getElementsByTagName("linestring");
    for(var i=0; i< linestrings.length; i++){
        var points = linestrings[i].getElementsByTagName("point");

        for(var ii=0; ii< points.length; ii++){
            if(ii+1 == points.length){
                break;
            }
            var p1 = new Point(points[ii].getElementsByTagName("x")[0].firstChild.nodeValue,
                points[ii].getElementsByTagName("y")[0].firstChild.nodeValue);
            var p2 =new Point(points[ii+1].getElementsByTagName("x")[0].firstChild.nodeValue,
                points[ii+1].getElementsByTagName("y")[0].firstChild.nodeValue);
            var line = new Line(p1,p2);
            line_path.add_graphics(line);
        }
        
    }
    return line_path;
};

/* Compute a Gaussian Elimination (RREF)
 * --------------------------------------------
 * arg. matrix is a multidimensional array
 * arg. dimension is the number of unknow values (es. 2x+4y=3 -> dimension 2)
 * returns a monodimension array containing the results (es. res[0] = x, res[1] = y, ...)
 */
Map_Wrapper.prototype.gauss_elimination = function(matrix, dimension)
{
    var n = dimension;
    var a = matrix;
    var i, j;
    var res = new Array();

    forwardSubstitution();
    reverseElimination();

    for (i = 0; i < n; ++i) {
        res[i] = a[i][n];
    }
    return res;

    function forwardSubstitution() {
        var i, j, k, max, t;
        for (i = 0; i < n; ++i) {
            max = i;
            for (j = i + 1; j < n; ++j)
            {
                if (a[j][i] > a[max][i])
                    max = j;
            }
            for (j = 0; j < n + 1; ++j) {
                t = a[max][j];
                a[max][j] = a[i][j];
                a[i][j] = t;
            }

            for (j = n; j >= i; --j)
            {
                for (k = i + 1; k < n; ++k)
                    a[k][j] -= a[k][i]/a[i][i] * a[i][j];
            }
        }
    }
    function reverseElimination() {
        var i, j;
        for (i = n - 1; i >= 0; --i) {
            a[i][n] = a[i][n] / a[i][i];
            a[i][i] = 1;
            for (j = i - 1; j >= 0; --j) {
                a[j][n] -= a[j][i] * a[i][n];
                a[j][i] = 0;
            }
        }
    }
};


Map_Wrapper.prototype.check_is_layer_selected = function (){
    if(_LAYER_SELECTED  == "" )
    {
        _OP_USER = new Idle();
        alert(_MSG_SELECT_LAYER);
        return false;
    }else{
        return true;
    }

};

Map_Wrapper.prototype.check_is_object_selected = function (){
    return (_LIST_OF_SELECTED_OBJECTS.length > 0);
};


function loaded_ref()
{
    loading_message(false);
    //Aggiutna della scala
    var div_scale = document.getElementById("scale");
    clear_node(div_scale);
    div_scale.appendChild(document.createTextNode(_MSG_SCALE+": 1:"+parseInt(_scale) ));

    var div = document.getElementById(_MAP_ID);
    clear_node(document.getElementById(_MAP_ID));

    //Sets the position of the map relative to its container
    div.style.left=_MAP_POSITION_LEFT;
    div.style.top=_MAP_POSITION_TOP;

    var img = document.createElement("img");
    div.appendChild(img);
    img.width=_w;
    img.height=_h;
    img.top="0px";
    img.left="0px";
    img.style.overflow="hidden";
    img.onload=function(){
        loaded_map();
    }
    img.src=_url_image;
    
}


function loaded_map()
{
    if(_LIST_OF_EXTRA_GRAPHICS == null || _LIST_OF_EXTRA_GRAPHICS.lenght == 0)
        alert('EXTRA_GRAPHICS NULL');
    
    document.getElementById("layers_container").style.visibility="visible";
	
    clear_extra_graphics(_ALL_DRAWING_ENGINES);
    draw_extra_graphics(true,_ALL_DRAWING_ENGINES);
	
    if(_WIN!=null && _WIN.close)
        _WIN.close();
   
}

