/* eslint-disable no-unused-vars */
import L from "leaflet"
export var Symbolizer = L.Class.extend({
	// 🍂method initialize(feature: GeoJSON, pxPerExtent: Number)
	// Initializes a new Line Symbolizer given a GeoJSON feature and the
	// pixel-to-coordinate-units ratio. Internal use only.

	// 🍂method render(renderer, style)
	// Renders this symbolizer in the given tiled renderer, with the given
	// `L.Path` options.  Internal use only.
	render: function(renderer, style) {
		this._renderer = renderer;
		this.options = style;
		renderer._initPath(this);
		renderer._updateStyle(this);
	},

	// 🍂method render(renderer, style)
	// Updates the `L.Path` options used to style this symbolizer, and re-renders it.
	// Internal use only.
	updateStyle: function(renderer, style) {
		this.options = style;
		renderer._updateStyle(this);
	},

	_getPixelBounds: function() {
		var parts = this._parts;
		var bounds = L.bounds([]);
		for (var i = 0; i < parts.length; i++) {
			var part = parts[i];
			for (var j = 0; j < part.length; j++) {
				bounds.extend(part[j]);
			}
		}

		var w = this._clickTolerance(),
            p = new L.Point(w, w);

		bounds.min._subtract(p);
		bounds.max._add(p);

		return bounds;
	},
	_clickTolerance: L.Path.prototype._clickTolerance,
})

export var PolyBase = {
	_makeFeatureParts: function(feat, pxPerExtent) {
		var rings = feat.geometry;
		var coord;

		this._parts = [];
		for (var i = 0; i < rings.length; i++) {
			var ring = rings[i];
			var part = [];
			for (var j = 0; j < ring.length; j++) {
				coord = ring[j];
				// Protobuf vector tiles return {x: , y:}
				// Geojson-vt returns [,]
				part.push(L.point(coord).scaleBy(pxPerExtent));
			}
			this._parts.push(part);
		}
	},

	makeInteractive: function() {
		this._pxBounds = this._getPixelBounds();
	}
}
export var LineSymbolizer = L.Polyline.extend({
	includes: [Symbolizer.prototype, PolyBase],

	initialize: function(feature, pxPerExtent) {
		this.properties = feature.properties;
		this._makeFeatureParts(feature, pxPerExtent);
	},

	render: function(renderer, style) {
		style.fill = false;
		Symbolizer.prototype.render.call(this, renderer, style);
		this._updatePath();
	},

	updateStyle: function(renderer, style) {
		style.fill = false;
		Symbolizer.prototype.updateStyle.call(this, renderer, style);
	},
})
export var FillSymbolizer = L.Polygon.extend({
	includes: [Symbolizer.prototype, PolyBase],

	initialize: function(feature, pxPerExtent) {
		this.properties = feature.properties;
		this._makeFeatureParts(feature, pxPerExtent);
	},

	render: function(renderer, style) {
		Symbolizer.prototype.render.call(this, renderer, style);
		this._updatePath();
	}
})
export var PointSymbolizer = L.CircleMarker.extend({
	includes: Symbolizer.prototype,

	statics: {
		iconCache: {}
	},

	initialize: function(feature, pxPerExtent) {
		this.properties = feature.properties;
		this._makeFeatureParts(feature, pxPerExtent);
	},

	render: function(renderer, style) {
		Symbolizer.prototype.render.call(this, renderer, style);
		this._radius = style.radius || L.CircleMarker.prototype.options.radius;
		this._updatePath();
	},

	_makeFeatureParts: function(feat, pxPerExtent) {
		var coord = feat.geometry[0];
		if (typeof coord[0] === 'object' && 'x' in coord[0]) {
			// Protobuf vector tiles return [{x: , y:}]
			this._point = L.point(coord[0]).scaleBy(pxPerExtent);
			this._empty = L.Util.falseFn;
		} else {
			// Geojson-vt returns [,]
			this._point = L.point(coord).scaleBy(pxPerExtent);
			this._empty = L.Util.falseFn;
		}
	},

	makeInteractive: function() {
		this._updateBounds();
	},

	updateStyle: function(renderer, style) {
		this._radius = style.radius || this._radius;
		this._updateBounds();
		return Symbolizer.prototype.updateStyle.call(this, renderer, style);
	},

	_updateBounds: function() {
		var icon = this.options.icon
		if (icon) {
			var size = L.point(icon.options.iconSize),
                anchor = icon.options.iconAnchor ||
                size && size.divideBy(2, true),
                p = this._point.subtract(anchor);
			this._pxBounds = new L.Bounds(p, p.add(icon.options.iconSize));
		} else {
			L.CircleMarker.prototype._updateBounds.call(this);
		}
	},

	_updatePath: function() {
		if (this.options.icon) {
			this._renderer._updateIcon(this)
		} else {
			L.CircleMarker.prototype._updatePath.call(this);
		}
	},

	_getImage: function () {
		if (this.options.icon) {
			var url = this.options.icon.options.iconUrl,
            img = PointSymbolizer.iconCache[url];
			if (!img) {
				var icon = this.options.icon;
				img = PointSymbolizer.iconCache[url] = icon.createIcon();
			}
			return img;
		} else {
			return null;
		}

	},

	_containsPoint: function(p) {
		var icon = this.options.icon;
		if (icon) {
			return this._pxBounds.contains(p);
		} else {
			return L.CircleMarker.prototype._containsPoint.call(this, p);
		}
	}
});

L.VectorGrid.prototype._createLayer=function(feat, pxPerExtent, layerStyle) {
    var layer;
    switch (feat.type) {
    case 1:
        layer = new PointSymbolizer(feat, pxPerExtent);
        // [YB 2019-10-23: prevent leaflet from treating these canvas points as real markers]
        layer.getLatLng = null;         
        break;
    case 2:
        layer = new LineSymbolizer(feat, pxPerExtent);
        break;
    case 3:
        layer = new FillSymbolizer(feat, pxPerExtent);
        break;
    }
  
    if (this.options.interactive) {
        layer.addEventParent(this);
    }
  
    return layer;
  }