text: /**
   * @module ol/format/MVT
   */
  //FIXME Implement projection handling
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = function (d, b) {
          extendStatics = Object.setPrototypeOf ||
              ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
              function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
          return extendStatics(d, b);
      };
      return function (d, b) {
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  import FeatureFormat, { transformGeometryWithOptions } from './Feature.js';
  import FormatType from './FormatType.js';
  import GeometryLayout from '../geom/GeometryLayout.js';
  import GeometryType from '../geom/GeometryType.js';
  import LineString from '../geom/LineString.js';
  import MultiLineString from '../geom/MultiLineString.js';
  import MultiPoint from '../geom/MultiPoint.js';
  import MultiPolygon from '../geom/MultiPolygon.js';
  import PBF from 'pbf';
  import Point from '../geom/Point.js';
  import Polygon from '../geom/Polygon.js';
  import Projection from '../proj/Projection.js';
  import RenderFeature from '../render/Feature.js';
  import Units from '../proj/Units.js';
  import { assert } from '../asserts.js';
  import { get } from '../proj.js';
  import { linearRingIsClockwise } from '../geom/flat/orient.js';
  /**
   * @typedef {Object} Options
   * @property {import("../Feature.js").FeatureClass} [featureClass] Class for features returned by
   * {@link module:ol/format/MVT#readFeatures}. Set to {@link module:ol/Feature~Feature} to get full editing and geometry
   * support at the cost of decreased rendering performance. The default is
   * {@link module:ol/render/Feature~RenderFeature}, which is optimized for rendering and hit detection.
   * @property {string} [geometryName='geometry'] Geometry name to use when creating features.
   * @property {string} [layerName='layer'] Name of the feature attribute that holds the layer name.
   * @property {Array<string>} [layers] Layers to read features from. If not provided, features will be read from all
   * @property {string} [idProperty] Optional property that will be assigned as the feature id and removed from the properties.
   * layers.
   */
  /**
   * @classdesc
   * Feature format for reading data in the Mapbox MVT format.
   *
   * @param {Options=} opt_options Options.
   * @api
   */
  var MVT = /** @class */ (function (_super) {
      __extends(MVT, _super);
      /**
       * @param {Options=} opt_options Options.
       */
      function MVT(opt_options) {
          var _this = _super.call(this) || this;
          var options = opt_options ? opt_options : {};
          /**
           * @type {Projection}
           */
          _this.dataProjection = new Projection({
              code: '',
              units: Units.TILE_PIXELS,
          });
          /**
           * @private
           * @type {import("../Feature.js").FeatureClass}
           */
          _this.featureClass_ = options.featureClass
              ? options.featureClass
              : RenderFeature;
          /**
           * @private
           * @type {string|undefined}
           */
          _this.geometryName_ = options.geometryName;
          /**
           * @private
           * @type {string}
           */
          _this.layerName_ = options.layerName ? options.layerName : 'layer';
          /**
           * @private
           * @type {Array<string>}
           */
          _this.layers_ = options.layers ? options.layers : null;
          /**
           * @private
           * @type {string}
           */
          _this.idProperty_ = options.idProperty;
          return _this;
      }
      /**
       * Read the raw geometry from the pbf offset stored in a raw feature's geometry
       * property.
       * @param {PBF} pbf PBF.
       * @param {Object} feature Raw feature.
       * @param {Array<number>} flatCoordinates Array to store flat coordinates in.
       * @param {Array<number>} ends Array to store ends in.
       * @private
       */
      MVT.prototype.readRawGeometry_ = function (pbf, feature, flatCoordinates, ends) {
          pbf.pos = feature.geometry;
          var end = pbf.readVarint() + pbf.pos;
          var cmd = 1;
          var length = 0;
          var x = 0;
          var y = 0;
          var coordsLen = 0;
          var currentEnd = 0;
          while (pbf.pos < end) {
              if (!length) {
                  var cmdLen = pbf.readVarint();
                  cmd = cmdLen & 0x7;
                  length = cmdLen >> 3;
              }
              length--;
              if (cmd === 1 || cmd === 2) {
                  x += pbf.readSVarint();
                  y += pbf.readSVarint();
                  if (cmd === 1) {
                      // moveTo
                      if (coordsLen > currentEnd) {
                          ends.push(coordsLen);
                          currentEnd = coordsLen;
                      }
                  }
                  flatCoordinates.push(x, y);
                  coordsLen += 2;
              }
              else if (cmd === 7) {
                  if (coordsLen > currentEnd) {
                      // close polygon
                      flatCoordinates.push(flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
                      coordsLen += 2;
                  }
              }
              else {
                  assert(false, 59); // Invalid command found in the PBF
              }
          }
          if (coordsLen > currentEnd) {
              ends.push(coordsLen);
              currentEnd = coordsLen;
          }
      };
      /**
       * @private
       * @param {PBF} pbf PBF
       * @param {Object} rawFeature Raw Mapbox feature.
       * @param {import("./Feature.js").ReadOptions} options Read options.
       * @return {import("../Feature.js").FeatureLike} Feature.
       */
      MVT.prototype.createFeature_ = function (pbf, rawFeature, options) {
          var type = rawFeature.type;
          if (type === 0) {
              return null;
          }
          var feature;
          var values = rawFeature.properties;
          var id;
          if (!this.idProperty_) {
              id = rawFeature.id;
          }
          else {
              id = values[this.idProperty_];
              delete values[this.idProperty_];
          }
          values[this.layerName_] = rawFeature.layer.name;
          var flatCoordinates = [];
          var ends = [];
          this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
          var geometryType = getGeometryType(type, ends.length);
          if (this.featureClass_ === RenderFeature) {
              feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
              feature.transform(options.dataProjection);
          }
          else {
              var geom = void 0;
              if (geometryType == GeometryType.POLYGON) {
                  var endss = [];
                  var offset = 0;
                  var prevEndIndex = 0;
                  for (var i = 0, ii = ends.length; i < ii; ++i) {
                      var end = ends[i];
                      // classifies an array of rings into polygons with outer rings and holes
                      if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
                          endss.push(ends.slice(prevEndIndex, i + 1));
                      }
                      else {
                          if (endss.length === 0) {
                              continue;
                          }
                          endss[endss.length - 1].push(ends[prevEndIndex]);
                      }
                      prevEndIndex = i + 1;
                      offset = end;
                  }
                  if (endss.length > 1) {
                      geom = new MultiPolygon(flatCoordinates, GeometryLayout.XY, endss);
                  }
                  else {
                      geom = new Polygon(flatCoordinates, GeometryLayout.XY, ends);
                  }
              }
              else {
                  geom =
                      geometryType === GeometryType.POINT
                          ? new Point(flatCoordinates, GeometryLayout.XY)
                          : geometryType === GeometryType.LINE_STRING
                              ? new LineString(flatCoordinates, GeometryLayout.XY)
                              : geometryType === GeometryType.POLYGON
                                  ? new Polygon(flatCoordinates, GeometryLayout.XY, ends)
                                  : geometryType === GeometryType.MULTI_POINT
                                      ? new MultiPoint(flatCoordinates, GeometryLayout.XY)
                                      : geometryType === GeometryType.MULTI_LINE_STRING
                                          ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends)
                                          : null;
              }
              var ctor = /** @type {typeof import("../Feature.js").default} */ (this
                  .featureClass_);
              feature = new ctor();
              if (this.geometryName_) {
                  feature.setGeometryName(this.geometryName_);
              }
              var geometry = transformGeometryWithOptions(geom, false, options);
              feature.setGeometry(geometry);
              feature.setId(id);
              feature.setProperties(values, true);
          }
          return feature;
      };
      /**
       * @return {import("./FormatType.js").default} Format.
       */
      MVT.prototype.getType = function () {
          return FormatType.ARRAY_BUFFER;
      };
      /**
       * Read all features.
       *
       * @param {ArrayBuffer} source Source.
       * @param {import("./Feature.js").ReadOptions=} opt_options Read options.
       * @return {Array<import("../Feature.js").FeatureLike>} Features.
       * @api
       */
      MVT.prototype.readFeatures = function (source, opt_options) {
          var layers = this.layers_;
          var options = /** @type {import("./Feature.js").ReadOptions} */ (this.adaptOptions(opt_options));
          var dataProjection = get(options.dataProjection);
          dataProjection.setWorldExtent(options.extent);
          options.dataProjection = dataProjection;
          var pbf = new PBF(/** @type {ArrayBuffer} */ (source));
          var pbfLayers = pbf.readFields(layersPBFReader, {});
          var features = [];
          for (var name_1 in pbfLayers) {
              if (layers && layers.indexOf(name_1) == -1) {
                  continue;
              }
              var pbfLayer = pbfLayers[name_1];
              var extent = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
              dataProjection.setExtent(extent);
              for (var i = 0, ii = pbfLayer.length; i < ii; ++i) {
                  var rawFeature = readRawFeature(pbf, pbfLayer, i);
                  features.push(this.createFeature_(pbf, rawFeature, options));
              }
          }
          return features;
      };
      /**
       * Read the projection from the source.
       *
       * @param {Document|Element|Object|string} source Source.
       * @return {import("../proj/Projection.js").default} Projection.
       * @api
       */
      MVT.prototype.readProjection = function (source) {
          return this.dataProjection;
      };
      /**
       * Sets the layers that features will be read from.
       * @param {Array<string>} layers Layers.
       * @api
       */
      MVT.prototype.setLayers = function (layers) {
          this.layers_ = layers;
      };
      return MVT;
  }(FeatureFormat));
  /**
   * Reader callback for parsing layers.
   * @param {number} tag The tag.
   * @param {Object} layers The layers object.
   * @param {PBF} pbf The PBF.
   */
  function layersPBFReader(tag, layers, pbf) {
      if (tag === 3) {
          var layer = {
              keys: [],
              values: [],
              features: [],
          };
          var end = pbf.readVarint() + pbf.pos;
          pbf.readFields(layerPBFReader, layer, end);
          layer.length = layer.features.length;
          if (layer.length) {
              layers[layer.name] = layer;
          }
      }
  }
  /**
   * Reader callback for parsing layer.
   * @param {number} tag The tag.
   * @param {Object} layer The layer object.
   * @param {PBF} pbf The PBF.
   */
  function layerPBFReader(tag, layer, pbf) {
      if (tag === 15) {
          layer.version = pbf.readVarint();
      }
      else if (tag === 1) {
          layer.name = pbf.readString();
      }
      else if (tag === 5) {
          layer.extent = pbf.readVarint();
      }
      else if (tag === 2) {
          layer.features.push(pbf.pos);
      }
      else if (tag === 3) {
          layer.keys.push(pbf.readString());
      }
      else if (tag === 4) {
          var value = null;
          var end = pbf.readVarint() + pbf.pos;
          while (pbf.pos < end) {
              tag = pbf.readVarint() >> 3;
              value =
                  tag === 1
                      ? pbf.readString()
                      : tag === 2
                          ? pbf.readFloat()
                          : tag === 3
                              ? pbf.readDouble()
                              : tag === 4
                                  ? pbf.readVarint64()
                                  : tag === 5
                                      ? pbf.readVarint()
                                      : tag === 6
                                          ? pbf.readSVarint()
                                          : tag === 7
                                              ? pbf.readBoolean()
                                              : null;
          }
          layer.values.push(value);
      }
  }
  /**
   * Reader callback for parsing feature.
   * @param {number} tag The tag.
   * @param {Object} feature The feature object.
   * @param {PBF} pbf The PBF.
   */
  function featurePBFReader(tag, feature, pbf) {
      if (tag == 1) {
          feature.id = pbf.readVarint();
      }
      else if (tag == 2) {
          var end = pbf.readVarint() + pbf.pos;
          while (pbf.pos < end) {
              var key = feature.layer.keys[pbf.readVarint()];
              var value = feature.layer.values[pbf.readVarint()];
              feature.properties[key] = value;
          }
      }
      else if (tag == 3) {
          feature.type = pbf.readVarint();
      }
      else if (tag == 4) {
          feature.geometry = pbf.pos;
      }
  }
  /**
   * Read a raw feature from the pbf offset stored at index `i` in the raw layer.
   * @param {PBF} pbf PBF.
   * @param {Object} layer Raw layer.
   * @param {number} i Index of the feature in the raw layer's `features` array.
   * @return {Object} Raw feature.
   */
  function readRawFeature(pbf, layer, i) {
      pbf.pos = layer.features[i];
      var end = pbf.readVarint() + pbf.pos;
      var feature = {
          layer: layer,
          type: 0,
          properties: {},
      };
      pbf.readFields(featurePBFReader, feature, end);
      return feature;
  }
  /**
   * @param {number} type The raw feature's geometry type
   * @param {number} numEnds Number of ends of the flat coordinates of the
   * geometry.
   * @return {import("../geom/GeometryType.js").default} The geometry type.
   */
  function getGeometryType(type, numEnds) {
      /** @type {import("../geom/GeometryType.js").default} */
      var geometryType;
      if (type === 1) {
          geometryType =
              numEnds === 1 ? GeometryType.POINT : GeometryType.MULTI_POINT;
      }
      else if (type === 2) {
          geometryType =
              numEnds === 1 ? GeometryType.LINE_STRING : GeometryType.MULTI_LINE_STRING;
      }
      else if (type === 3) {
          geometryType = GeometryType.POLYGON;
          // MultiPolygon not relevant for rendering - winding order determines
          // outer rings of polygons.
      }
      return geometryType;
  }
  export default MVT;
  //# sourceMappingURL=MVT.js.map