// Shapefile parser, following the specification at
// http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf
SHP = {
  NULL: 0,
  POINT: 1,
  POLYLINE: 3,
  POLYGON: 5
};

SHP.getShapeName = function (id) {
  for (name in this) {
    if (id === this[name]) {
      return name;
    }
  }
};

SHPParser = function () {
};

SHPParser.load = function (src, callback, onerror) {
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'arraybuffer';
  xhr.onload = function () {
    var d = new SHPParser().parse(xhr.response, xhr);
    if (d) {
      callback(d);
    }
  };
  xhr.onerror = onerror;
  xhr.open('GET', src);
  xhr.send(null);
};

SHPParser.prototype.parse = function (arrayBuffer, xhr) {
  var o = {};
  var dv = new DataView(arrayBuffer);
  var idx = 0;
  o.fileCode = dv.getInt32(idx, false);
  if (o.fileCode != 0x0000270a) {
    // throw (new Error("Unknown file code: " + o.fileCode));
    xhr.onerror();
    return false;
  }
  idx += 6 * 4;
  o.wordLength = dv.getInt32(idx, false);
  o.byteLength = o.wordLength * 2;
  idx += 4;
  o.version = dv.getInt32(idx, true);
  idx += 4;
  o.shapeType = dv.getInt32(idx, true);
  idx += 4;
  o.minX = dv.getFloat64(idx, true);
  o.minY = dv.getFloat64(idx + 8, true);
  o.maxX = dv.getFloat64(idx + 16, true);
  o.maxY = dv.getFloat64(idx + 24, true);
  o.minZ = dv.getFloat64(idx + 32, true);
  o.maxZ = dv.getFloat64(idx + 40, true);
  o.minM = dv.getFloat64(idx + 48, true);
  o.maxM = dv.getFloat64(idx + 56, true);
  idx += 8 * 8;
  o.records = [];
  while (idx < o.byteLength) {
    var record = {};
    record.number = dv.getInt32(idx, false);
    idx += 4;
    record.length = dv.getInt32(idx, false);
    idx += 4;
    try {
      record.shape = this.parseShape(dv, idx, record.length);
    } catch (e) {
      console.log(e, record);
    }
    idx += record.length * 2;
    o.records.push(record);
  }
  return o;
};

SHPParser.prototype.parseShape = function (dv, idx, length) {
  var i = 0, c = null;
  var shape = {};
  shape.type = dv.getInt32(idx, true);
  idx += 4;
  var byteLen = length * 2;
  switch (shape.type) {
    case SHP.NULL: // Null
      break;

    case SHP.POINT: // Point (x,y)
      shape.content = {
        x: dv.getFloat64(idx, true),
        y: dv.getFloat64(idx + 8, true)
      };
      break;
    case SHP.POLYLINE: // Polyline (MBR, partCount, pointCount, parts, points)
    case SHP.POLYGON: // Polygon (MBR, partCount, pointCount, parts, points)
      c = shape.content = {
        minX: dv.getFloat64(idx, true),
        minY: dv.getFloat64(idx + 8, true),
        maxX: dv.getFloat64(idx + 16, true),
        maxY: dv.getFloat64(idx + 24, true),
        parts: new Int32Array(dv.getInt32(idx + 32, true)),
        points: new Float64Array(dv.getInt32(idx + 36, true) * 2)
      };
      idx += 40;
      for (i = 0; i < c.parts.length; i++) {
        c.parts[i] = dv.getInt32(idx, true);
        idx += 4;
      }
      for (i = 0; i < c.points.length; i++) {
        c.points[i] = dv.getFloat64(idx, true);
        idx += 8;
      }
      break;

    case 8: // MultiPoint (MBR, pointCount, points)
    case 11: // PointZ (X, Y, Z, M)
    case 13: // PolylineZ
    case 15: // PolygonZ
    case 18: // MultiPointZ
    case 21: // PointM (X, Y, M)
    case 23: // PolylineM
    case 25: // PolygonM
    case 28: // MultiPointM
    case 31: // MultiPatch
      throw new Error("Shape type not supported: "
        + shape.type + ':' +
        + SHP.getShapeName(shape.type));
    default:
      throw new Error("Unknown shape type at " + (idx - 4) + ': ' + shape.type);
  }
  return shape;
};

        // if (isRoad) {
        //   // Three�����廭��
        //   var geometry = new THREE.LineGeometry();
        //   var decoPos = [];
        //   var spline = new THREE.CatmullRomCurve3(poly);
        //   var color = new THREE.Color();
        //   var colors = [];
        //   for (var m = 0, l = poly.length * 120; m <= l; m++) {
        //     var point = spline.getPoint(m / l);
        //     decoPos.push(point.x, point.y, point.z);
        //     // if (m == 0 || m == 1 || m == 2) {
        //     //   colors.push(1.0, 1.0, 0.0);
        //     // } else if (m == 3) {
        //     //   colors.push(1.0, 1.0, 0.0);
        //     // } else {
        //     //   colors.push(1.0, 0.0, 0.0);
        //     // }
        //   }
        //   geometry.setPositions(decoPos);
        //   // geometry.setColors(colors);
        //   var line = new THREE.Line2(geometry, matLine);
        //   line.computeLineDistances();
        //   line.scale.set(1, 1, 1);
        //   line.position.z += 15000.0;
        //   // line.rotation.x = Math.PI / 2;
        //   scene.add(line);
        //   line.userData.posCount = poly.length * 12;
        //   line.userData.index = 0;
        //   line.userData.flag = 0;
        //   line.layers.enable(BLOOM_SCENE);

        //   // ���ڸ���mesh����
        //   obj = new _3DObject();
        //   obj.threeMesh = line;
        //   obj.minWGS84 = [r.content.minX, r.content.minY];
        //   obj.maxWGS84 = [r.content.maxX, r.content.maxY];
        //   _3Dobjects.push(obj);
        // }




                    // var line = _3DLineobjects[id].threeMesh;
                    // var posCount = line.userData.posCount;

                    // var colors = [];
                    // if (line.userData.index == posCount) {
                    //     line.userData.index = 0;
                    // }
                    // for (var i = 0, l = posCount; i <= l; i++) {
                    //     if (i == line.userData.index || i == line.userData.index + 1 || i == line.userData.index + 2) {
                    //         colors.push(1.0, 1.0, 0.0);
                    //     } else if (i == line.userData.index - 1) {
                    //         colors.push(1.0, 1.0, 0.0);
                    //     } else {
                    //         colors.push(1.0, 0.0, 0.0);
                    //         // colors.push(0,1,1);
                    //         // colors.push(1.0, 0.0, 0.0);
                    //     }
                    // }
                    // line.geometry.setColors(colors);
                    // line.userData.index++;