// Ref.: https://deck.gl/docs/developer-guide/custom-layers/composite-layers
import { CompositeLayer } from '@deck.gl/core';
import { GeoJsonLayer, ColumnLayer } from '@deck.gl/layers';

class DougalEventsLayer extends CompositeLayer {
  static layerName = "DougalEventsLayer";

  static defaultProps = {
    columnsZoom: 11, // Threshold zoom level for switching layers
    jitter: 0, // Add a small amount of jitter so that columns do not overlap.
    // GeoJsonLayer props
    getLineColor: [127, 65, 90],
    getFillColor: [127, 65, 90],
    getPointRadius: 2,
    radiusUnits: "pixels",
    pointRadiusMinPixels: 2,
    lineWidthMinPixels: 2,
    // ColumnLayer props
    getPosition: { type: 'accessor', value: d => d.geometry.coordinates },
    getElevation: { type: 'accessor', value: d => Math.min(Math.max(d.properties.remarks?.length || 10, 10), 200) },
    diskResolution: 20,
    radius: 5,
    radiusUnits: "pixels",
    radiusScale: 1,
    elevationScale: 1,
    filled: true,
    stroked: false,
    extruded: true,
    wireframe: false,
    material: true,
    getFillColor: [255, 0, 0, 200],
    getLineColor: [255, 0, 0, 200],
    getLineWidth: 2,
    pickable: true
  }

  constructor(props) {
    super(props);
    this.uid = "el-" + Math.random().toString().slice(2);
    // Initialize state with current zoom
    this.state = {
      zoom: this.context?.viewport?.zoom || 0
    };
  }

  shouldUpdateState({ changeFlags }) {
    // Always update if viewport changed (including zoom)
    if (changeFlags.viewportChanged) {
      return true;
    }
    return super.shouldUpdateState({ changeFlags });
  }

  updateState({ props, oldProps, context, changeFlags }) {
    // Check if zoom has changed
    const newZoom = context.viewport?.zoom || 0;
    if (newZoom !== this.state.zoom) {
      this.setState({ zoom: newZoom });
      this.setNeedsRedraw(); // Trigger re-render of sublayers
      console.log(`Zoom changed to ${newZoom}, triggering redraw`);
    }
  }

  getPickingInfo({ info, mode, sourceLayer }) {
    if (info.index >= 0) {
      info.object = {
        ...info.object // Merge default picking info (GeoJSON feature or ColumnLayer object)
      };
      if (sourceLayer) {
        info.object.type = sourceLayer.constructor.layerName;
      }
      //console.log(`Picked ${info.object.type}, index ${info.index}`);
    }
    return info;
  }

  renderLayers() {
    const { zoom } = this.state;
    const sublayers = [];

    if (zoom >= this.props.columnsZoom) {
      // Render ColumnLayer at high zoom
      const data = Array.isArray(this.props.data) ? this.props.data : this.props.data.features || [];

      const positionFn = this.props.jitter
        ? (d, info) => {
          let pos;
          if (typeof this.props.getPosition == 'function') {
            pos = this.props.getPosition(d, info);
          } else {
            pos = this.props.getPosition;
          }
            return pos.map( i => i + (Math.random() - 0.5) * this.props.jitter )
        }
        : this.props.getPosition;

      sublayers.push(
        new ColumnLayer(this.getSubLayerProps({
          id: `${this.uid}-column`,
          data,
          visible: this.props.visible,
          getPosition: positionFn,
          getElevation: this.props.getElevation,
          diskResolution: this.props.diskResolution,
          radius: this.props.radius,
          radiusUnits: this.props.radiusUnits,
          radiusScale: this.props.radiusScale,
          elevationScale: this.props.elevationScale,
          filled: this.props.filled,
          stroked: this.props.stroked,
          extruded: this.props.extruded,
          wireframe: this.props.wireframe,
          material: this.props.material,
          getFillColor: this.props.getFillColor,
          getLineColor: this.props.getLineColor,
          getLineWidth: this.props.getLineWidth,
          pickable: this.props.pickable
        }))
      );
    } else {
      // Render GeoJsonLayer at low zoom
      sublayers.push(
        new GeoJsonLayer(this.getSubLayerProps({
          id: `${this.uid}-geojson`,
          data: this.props.data,
          visible: this.props.visible,
          getLineColor: this.props.getLineColor,
          getFillColor: this.props.getFillColor,
          getPointRadius: this.props.getPointRadius,
          radiusUnits: this.props.radiusUnits,
          pointRadiusMinPixels: this.props.pointRadiusMinPixels,
          lineWidthMinPixels: this.props.lineWidthMinPixels,
          pickable: this.props.pickable
        }))
      );
    }

    console.log(`Rendering ${sublayers.length} sublayer(s) at zoom ${zoom}`);

    return sublayers;
  }
}

export default DougalEventsLayer;
