//Extend esri.geometry.Extent to include an erase method.  
//The erease method works on an extent and erases that extent based on the passed in extent.
//It returns an esri.geometry.Polygon which contains the erased extent
//The main use case for this method is to get the new area of a map as a polygon when the user pans.
//That result polygon can be used in a query task to query only new features in the map extent.
dojo.extend(esri.geometry.Extent, {
  erase: function(extent) {   
    var e1 = this;      //first extent
    var e2 = extent;    //second extent
    var sr = this.spatialReference;
    if (e1.xmin < e2.xmin && e1.xmax > e2.xmax && e1.ymin < e2.ymin && e1.ymax > e2.ymax) {
              //e1 contains e2; e2 is an inner ring (hole) of e1
              var innerPoints = [new esri.geometry.Point(e2.xmax,e2.ymax,sr),
                            new esri.geometry.Point(e2.xmin,e2.ymax,sr),
                            new esri.geometry.Point(e2.xmin,e2.ymin,sr),
                            new esri.geometry.Point(e2.xmax,e2.ymin,sr),
                            new esri.geometry.Point(e2.xmax,e2.ymax,sr)];
              var points = [new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                            new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                            new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                            new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                            new esri.geometry.Point(e1.xmax,e1.ymax,sr)];   
              var erasedPolygon = new esri.geometry.Polygon(sr);
              erasedPolygon.addRing(points);
              erasedPolygon.addRing(innerPoints);
              return erasedPolygon;                         
    } else if (e1.xmin > e2.xmin && e1.xmax < e2.xmax && e1.ymin > e2.ymin && e1.ymax < e2.ymax) {
      //e2 completely contains e1; all of e1 is erased.
      return null;
    } else if (e1.xmin > e2.xmin && e1.ymin < e2.ymin) {
      //moved to nw
      var points = [new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e2.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e2.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymax,sr)];
    } else if (e1.xmin < e2.xmin && e1.ymin < e2.ymin) {
      //moved to ne
      var points = [new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmax,e2.ymin,sr),
                    new esri.geometry.Point(e2.xmin,e2.ymin,sr),
                    new esri.geometry.Point(e2.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymax,sr)];
    } else if (e1.xmin < e2.xmin && e1.ymin > e2.ymin) {
      //moved to se
      var points = [new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e2.ymax,sr),
                    new esri.geometry.Point(e2.xmin,e2.ymax,sr),
                    new esri.geometry.Point(e2.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymin,sr)];
    } else if (e1.xmin > e2.xmin && e1.ymin > e2.ymin) {
      //moved to sw
      var points = [new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e2.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e2.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymax,sr)];
    } else if (e1.xmin === e2.xmin && e1.ymin < e2.ymin) {
      //moved to south
      var points = [new esri.geometry.Point(e1.xmin,e2.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmax,e2.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e2.ymin,sr)];
    } else if (e1.xmin === e2.xmin && e1.ymin > e2.ymin) {
      //moved to north
      var points = [new esri.geometry.Point(e1.xmin,e2.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e2.ymax,sr),
                    new esri.geometry.Point(e1.xmin,e2.ymax,sr)];
    } else if (e1.xmin < e2.xmin && e1.ymin === e2.ymin) {
      //moved to west
      var points = [new esri.geometry.Point(e1.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e2.xmin,e1.ymax,sr),
                    new esri.geometry.Point(e2.xmin,e1.ymin,sr),
                    new esri.geometry.Point(e1.xmin,e1.ymin,sr)];
    } else if (e1.xmin > e2.xmin && e1.ymin === e2.ymin) {
      //moved to east
      var points = [new esri.geometry.Point(e2.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymax,sr),
                    new esri.geometry.Point(e1.xmax,e1.ymin,sr),
                    new esri.geometry.Point(e2.xmax,e1.ymin,sr)];
    }
    
    var erasedPolygon = new esri.geometry.Polygon(sr);
    erasedPolygon.addRing(points);
    return erasedPolygon;
  }
});
