var BIGPOLYLINE_SEGMENTSIZE = 256;
// Douglas-Poiker

function BigPolyline(latlngs, color, weight, opacity, opts) {
  GOverlay();
  this.groups = [];
  this.visibleSegments = [];
  this.maxVisibleSegments = 5;

  var lastGroupSize = 2;  // dummy value
  
  function createPolyline(latlngs) {
    return new google.maps.Polyline(latlngs, color, weight, opacity, opts);
  }

  while (lastGroupSize > 1) {
    var group = [];
    var segmentLatlngs = [];
    var skipValue = Math.pow(2, this.groups.length);
    
    for (var i = 0; i < latlngs.length; i += skipValue) {
      segmentLatlngs.push(latlngs[i]);
      if (segmentLatlngs.length >= BIGPOLYLINE_SEGMENTSIZE) {
        group.push(createPolyline(segmentLatlngs));
        
        // a single point of overlap
	      segmentLatlngs = [ latlngs[i] ];
      }
    }
    
    group.push(createPolyline(segmentLatlngs));
    
    this.groups.push(group);
    lastGroupSize = group.length;
  }
}

BigPolyline.prototype.initialize = function(map) {
  for (var g = 0; g < this.groups.length; g++) {
    var group = this.groups[g];
    for (var s = 0; s < group.length; s++) {
      var segment = group[s];
      segment.initialize(map);
      segment.hide();
    }
  }

  this.map = map;
}

BigPolyline.prototype.redraw = function(force) {

  for (var segmentNum = 0; segmentNum < this.visibleSegments.length; segmentNum++) {
     this.visibleSegments[segmentNum].hide();
  }
  
  this.visibleSegments = this.getVisibleSegments(this.map.getBounds());
  
  for (var segmentNum = 0; segmentNum < this.visibleSegments.length; segmentNum++) {
    this.visibleSegments[segmentNum].show();
  }

/*  var oldVisibleSegments = this.visibleSegments;
  this.visibleSegments = this.getVisibleSegments(this.map.getBounds());


   
  for (var segmentNum = 0; segmentNum < this.visibleSegments.length; segmentNum++) {
    var thisSegment = this.visibleSegments[segmentNum];
    thisSegment.show();
    for (var oldSegmentNum = 0; oldSegmentNum < oldVisibleSegments.length; oldSegmentNum++) {
      if (thisSegment == oldVisibleSegments[oldSegmentNum]) {
        oldVisibleSegments[oldSegmentNum] = null;
        break;
      }
    }
  }

  for (var oldSegmentNum = 0; oldSegmentNum < oldVisibleSegments.length; oldSegmentNum++) {
    oldVisibleSegments[oldSegmentNum] && oldVisibleSegments[oldSegmentNum].hide();
  }
  */
  // Now that we've shown and hidden the right polylines, send redraw calls to _all_ of them.
  for (var g = 0; g < this.groups.length; g++) {
    var group = this.groups[g];
    for (var s = 0; s < group.length; s++) {
      group[s].redraw(force);
    }
  }
}

BigPolyline.prototype.getVisibleSegments = function(bounds) {
  var groupNum = this.groups.length - 1;
  var thisGroup = [ 0 ];
  var me = this;

  function getSegments(groupNum, segmentIds) {
    var segments = []; 
    for (var segmentIdNum = 0; segmentIdNum < segmentIds.length; segmentIdNum++) {
      segments.push(me.groups[groupNum][segmentIds[segmentIdNum]]);
    }
    return segments;
  }

  while (groupNum > 0) {
    lastGroup = thisGroup;
    thisGroup = [];
    groupNum--;
    
    for (var lastGroupIter = 0; lastGroupIter < lastGroup.length; lastGroupIter++) {
      var lastGroupSegmentNum = lastGroup[lastGroupIter];
      for (var plusOne = 0; plusOne <= 1; plusOne++) {
        var segmentNum = lastGroupSegmentNum * 2 + plusOne;
        if (this.groups[groupNum][segmentNum] && 
            this.groups[groupNum][segmentNum].getBounds().intersects(bounds)) {
                thisGroup.push(segmentNum);
        }
      }
    }

    if (thisGroup.length > this.maxVisibleSegments) {
      return getSegments(groupNum + 1, lastGroup);
    }
  }

  return getSegments(groupNum, thisGroup);
}

BigPolyline.prototype.remove = function() {
}

BigPolyline.prototype.copy = function() {
}
