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;	
}

Map_Wrapper.prototype.update_map=function(url,url_scale,url_ref,scale,minx,maxx,miny,maxy,w,h)
{
    try{
        //Save the extent
        this._minx=new Number(minx);
        this._maxx=new Number(maxx);
        this._miny=new Number(miny);
        this._maxy=new Number(maxy);
        this._width=new Number(w);
        this._height=new Number(h);
        this._scale= new Number(scale);
        _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 (_COORDINATES_PRECISION != 0)
    {
        return new Array(parseFloat( new Number(x_map).toFixed(_COORDINATES_PRECISION) ),
            (new Number(y_map ).toFixed(_COORDINATES_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.get_width() )/(this._maxx-this._minx);
    var y_pxl=( (y-this._miny) *this.get_height() )/(this._maxy-this._miny);
    y_pxl=inv ? this.get_height()-y_pxl : y_pxl;
    return new Array(parseInt(x_pxl),parseInt(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.get_width=function()
{
    return this._width;
};

Map_Wrapper.prototype.get_height=function()
{
    return this._height;
};

Map_Wrapper.prototype.get_scale=function()
{
    return parseInt(this._scale);
};

Map_Wrapper.prototype.clear_map=function()
{
    clear_node(document.getElementById(_MAP_ID));
//document.getElementById(_MAP_ID).style.visibility="hidden";
};

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.vectors_angle=function(v1,v2)
{
    // Formula for calculating the angle between two vectors
    // cos(alfa) = a dot b / |a|*|b|
    // alfa = arcos( cos(alfa) )	
    // Prodotto scalare rispetto a vettore asse x
    var scalare= v1[0]*v2[0]+v1[1]*v2[1];		
    // Norma del vettore della base
    var n_base = Math.sqrt(Math.pow(v1[0],2)+Math.pow(v1[1],2));	
    // Norma del vettore di spostamento
    var n_spost = Math.sqrt(Math.pow(v2[0],2)+Math.pow(v2[1],2));	
    return Math.acos(scalare/(n_base*n_spost));
};

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( 
        _MAP_WRAPPER.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;
};

Map_Wrapper.prototype.decode_line_path_from_xml = function(xml_compound_curve)
{
    var line_path = new Line_Path();
    line_path.add_list_of_graphics( this.decode_line_path_components_from_xml(xml_compound_curve) );
    return line_path;
};
Map_Wrapper.prototype.decode_line_path_from_xml_list = function(xml)
{
    var compound_curves=xml.getElementsByTagName("list_of_compound_curve")[0];
	
    var line_path = new Line_Path();
	
    for(var i=0;i<compound_curves.childNodes.length;i++)
    {
        var elem = compound_curves.childNodes[i];
        line_path.add_list_of_graphics( this.decode_line_path_components_from_xml(elem) );	
    }
    return line_path;

};
Map_Wrapper.prototype.decode_line_path_components_from_xml = function(xml_compound_curve)
{
    var list_of_obj  = new Array();
   	
    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);
            list_of_obj.push( new Arc(p1,p2,p3) );
   			
        }
        if(elem.nodeName == "line" )
        {
            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);
            list_of_obj.push( new Line(p1,p2) );
        }
             			
    }
   	
    return list_of_obj;

};

Map_Wrapper.prototype.decode_polygon_from_xml = function(xml_polygon)
{
    var polygon = new Polygon();
    var points = xml_polygon.getElementsByTagName("point");
    for(var i = 0; i< points.length; i++)
    {
        var p1 = new Point(points[i].getElementsByTagName("x")[0].firstChild.nodeValue,
            points[i].getElementsByTagName("y")[0].firstChild.nodeValue);
        if(i+1 == points.length)
            return polygon;
		
        var p2 = new Point(points[i+1].getElementsByTagName("x")[0].firstChild.nodeValue,
            points[i+1].getElementsByTagName("y")[0].firstChild.nodeValue);
		
        polygon.add_graphics(new Line(p1,p2));
		
    }
};

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 );
        list_of_points.push(point);
    }
    
    return list_of_points;
};


Map_Wrapper.prototype.decode_point_from_xml = function(xml_point){
    return new Point( xml_point.getElementsByTagName("point")[0].getElementsByTagName("x")[0].
        firstChild.nodeValue,xml_point.getElementsByTagName("point")[0].getElementsByTagName("y")[0].
        firstChild.nodeValue );
};

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;
            }
        }
    }
}
/*
 * Compute intersection between a line and a circle
 * -------------------------------------------------
 * arg. line is a line object
 * arg. circle is a circle object
 * returns an array containing the results intersection points
 * or false if there are not intersections
 */
Map_Wrapper.prototype.line_intersect_circle = function (line,circle)
{
   var a,b,c;
   var bb4ac;
   var dp = new Point();
   var p1 = line._p1;
   var p2 = line._p2;
   var sc = circle._center;
   var r = circle._ray;
   var mu1,mu2;

   dp._x = p2._x - p1._x;
   dp._y = p2._y - p1._y;

   a = dp._x * dp._x + dp._y * dp._y;
   b = 2 * (dp._x * (p1._x - sc._x) + dp._y * (p1._y - sc._y));
   c = sc._x * sc._x + sc._y * sc._y;
   c += p1._x * p1._x + p1._y * p1._y;
   c -= 2 * (sc._x * p1._x + sc._y * p1._y);
   c -= r * r;
   bb4ac = b * b - 4 * a * c;
   if ( bb4ac < 0) {
      mu1 = 0;
      mu2 = 0;
      return false;
   }
   mu1 = (-b + Math.sqrt(bb4ac)) / (2 * a);
   mu2 = (-b - Math.sqrt(bb4ac)) / (2 * a); 

   var iP1 = new Point((p1._x + mu1 *(p2._x - p1._x)), (p1._y + mu1 *(p2._y - p1._y)));
   var iP2 = new Point((p1._x + mu2 *(p2._x - p1._x)), (p1._y + mu2 *(p2._y - p1._y)));

   var iPoints = new Array();
   iPoints[0] = iP1;
   iPoints[1] = iP2;

   return iPoints;

}


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) ));
	
    //Add scalebar image
    var div_scale_image=document.getElementById("scale_image");
    clear_node(div_scale_image);
    var img_scalebar = document.createElement("img");
    div_scale_image.appendChild(img_scalebar);
    img_scalebar.onload= function(){
        loaded_scale();
    }
    img_scalebar.src=_url_scale;
	
}

function loaded_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();
    draw_extra_graphics(true);
	
    if(_WIN!=null && _WIN.close)
        _WIN.close();
   
}

