/*
 * encapsulates the <ENVELOPE> element found in several types of AXL responses.
 * As with many simple JS objects, the accessor methods are unnecessary, but 
 * only provided for completeness. fields may also be accessed directly.
 * 
 * TODO: this class may be expanded to provide extra info on the represented
 * envelope, e.g. aspect ratio, area, etc.
 */
 
 
/**
 * constructor for Envelope class. expects to be given an an <ENVELOPE> element,
 * e.g. <ENVELOPE minx="-180" miny="-126" maxx="180" maxy="126" />
 */
function Envelope(node) {
   this.minX = null;
   this.minY = null;
   this.maxX = null;
   this.maxY = null;
   
   if (node) {
      this.minX = parseFloat(node.getAttributeNode('minx').nodeValue);
      this.minY = parseFloat(node.getAttributeNode('miny').nodeValue);
      this.maxX = parseFloat(node.getAttributeNode('maxx').nodeValue);
      this.maxY = parseFloat(node.getAttributeNode('maxy').nodeValue);
   }
}

Envelope.prototype.trimGeo=function() {
   if (-180.0 > this.minX) { this.minX = -180.0; }
   if (-90.0 > this.minY)  { this.minY = -90.0;  }
   if (180.0 < this.maxX)  { this.maxX = 180.0;  }
   if (90.0 < this.maxY)   { this.maxY = 90.0;   }
}

/**
 * convenience function for resetting coords
 */
Envelope.prototype.setCoords=function(minx,miny,maxx,maxy) {
   this.minX = minx;
   this.minY = miny;
   this.maxX = maxx;
   this.maxY = maxy;
}

Envelope.prototype.getXDistance=function() {
   return(Math.abs(this.maxX - this.minX));
}

Envelope.prototype.getYDistance=function() {
   return(Math.abs(this.maxY - this.minY));
}

Envelope.prototype.getMinX=function() {
   return(this.minX);
}

Envelope.prototype.getMinY=function() {
   return(this.minY);
}

Envelope.prototype.getMaxX=function() {
   return(this.maxX);
}

Envelope.prototype.getMaxY=function() {
   return(this.maxY);
}

Envelope.prototype.toString=function() {
   var str = "<ENVELOPE minx=\""+this.minX+"\" miny=\""+this.minY+"\" ";
   str += "maxx=\""+this.maxX+"\" maxy=\""+this.maxY+"\" />";
   return(str);
}

Envelope.prototype.toCSV=function() {
   return(this.minX+","+this.minY+","+this.maxX+","+this.maxY);
}

/**
 * return this envelope in a pseudo-WKT format
 */
Envelope.prototype.toWKT=function() {
   return('ENVELOPE(('+this.minX+' '+this.minY+', '+this.maxX+' '+this.maxY+'))');
}

/**
 * returns a new copy of this envelope w/ the coordinate precision reduced to 
 * the specified number of decimal places
 */
Envelope.prototype.getPrecisionEnvelope=function(numDecimals) {
   var u = Math.pow(10,numDecimals);
   var minX = Math.round(this.minX * u) / u;
   var minY = Math.round(this.minY * u) / u;
   var maxX = Math.round(this.maxX * u) / u;
   var maxY = Math.round(this.maxY * u) / u;
   return (new EnvelopeFloat(minX,minY,maxX,maxY));
}


/**
 * returns the union of this envelope w/ the one provided
 */
Envelope.prototype.union=function(env) {
   if (env === null) { return(this); }
   if (env.minX < this.minX) { this.minX = env.minX; }
   if (env.minY < this.minY) { this.minY = env.minY; }
   if (env.maxX > this.maxX) { this.maxX = env.maxX; }
   if (env.maxY > this.maxY) { this.maxY = env.maxY; }
}

/**
 * expand the envelope (in all directions) by the given amount
 * @TODO constrain to limitEnvelope?
 */
Envelope.prototype.expand=function(deltaX,deltaY) {
   this.minX = this.minX - deltaX;
   this.minY = this.minY - deltaX;
   this.maxX = this.maxX + deltaX;
   this.maxY = this.maxY + deltaY;    
}

  
/**
 * subclass to mimic overloaded constructor
 */
function EnvelopeFloat(minx,miny,maxx,maxy) {
      this.minX = minx;
      this.minY = miny;
      this.maxX = maxx;
      this.maxY = maxy;
}
EnvelopeFloat.prototype = new Envelope();
EnvelopeFloat.prototype.constructor = EnvelopeFloat;


/**
 * subclass to mimic overloaded constructor
 */
function EnvelopeString(coords) {
   //expect comma-separated string in the format of "minx,miny,maxx,maxy"
   var list  = coords.split(',');
   this.minX = parseFloat(list[0]);
   this.minY = parseFloat(list[1]);
   this.maxX = parseFloat(list[2]);
   this.maxY = parseFloat(list[3]);
}
EnvelopeString.prototype = new Envelope();
EnvelopeString.prototype.constructor = EnvelopeString;
