import { getAllLayer, getLayer } from '@/services/controller/MapController';
import { INITIAL_VIEW_CONFIG, osmLayer } from '@/services/service/MapService';
import {
  createGeoJSONLayer,
  createLabelAndFillStyle,
  OL_PROJECTION,
} from '@/utils/mapUtils';
import { Feature, Map, View } from 'ol';
import { Coordinate } from 'ol/coordinate';
import { easeOut } from 'ol/easing';
import { EventsKey } from 'ol/events';
import { createEmpty, extend, Extent, isEmpty } from 'ol/extent';
import { LineString, MultiPolygon, Point, Polygon } from 'ol/geom';
import BaseLayer from 'ol/layer/Base';
import VectorLayer from 'ol/layer/Vector';
import { unByKey } from 'ol/Observable';
import { fromLonLat } from 'ol/proj';
import { getVectorContext } from 'ol/render';
import RenderEvent from 'ol/render/Event';
import VectorSource from 'ol/source/Vector';
import { Circle as CircleStyle, Style } from 'ol/style';
import Fill from 'ol/style/Fill';
import Icon from 'ol/style/Icon';
import Stroke from 'ol/style/Stroke';
import Text from 'ol/style/Text';

interface MapManagerConfig {
  onFeatureClick?: (feature: any) => void;
  onFeatureSelect?: (feature: any, pixel: any) => void;
  onFeaturesClick?: (features: any[]) => void;
  onError?: (error: string[]) => void;
}
interface AnimationConfig {
  duration?: number;
  maxRadius?: number;
  strokeColor?: string;
  strokeWidthBase?: number;
}

interface StyleConfig {
  icon?: string; // URL của icon
  font?: string; // font chữ cho text
  textColor?: string; // màu chữ
  textStrokeColor?: string; // màu viền chữ
  textOffsetY?: number; // độ lệch theo trục Y
  strokeColor?: string; // màu đường kẻ cho LineString
  strokeWidth?: number; // độ dày đường kẻ cho LineString
  fillColor?: string; // màu fill cho Polygon
  borderColor?: string; // màu viền cho Polygon
  borderWidth?: number; // độ dày viền cho Polygon
  minScale?: number; // tỷ lệ nhỏ nhất
  maxScale?: number; // tỷ lệ lớn nhất
}

// Interface for feature data
interface FeatureData {
  id?: string | number;
  bearing?: number;
  text?: string;
}

// Interface for layer object
interface Layer {
  layer: VectorLayer<VectorSource>;
}

class MapManager {
  mapRef: React.RefObject<HTMLDivElement>;
  map: Map | null;
  featureLayer: VectorLayer<VectorSource> | null;
  private features: Feature[];
  private zoomListenerAdded: boolean;
  private onFeatureClick: (feature: Feature) => void;
  private onFeatureSelect: (feature: Feature, pixel: number[]) => void;
  private onFeaturesClick: (features: Feature[]) => void;
  private onError: (errors: string[]) => void;
  private errors: string[];
  private layers: BaseLayer[]; // Assuming layers is defined elsewhere
  private isInitialized: boolean; // Thêm thuộc tính để theo dõi trạng thái khởi tạo
  private eventKey: EventsKey | undefined;

  constructor(
    mapRef: React.RefObject<HTMLDivElement>,
    config: MapManagerConfig = {},
  ) {
    this.mapRef = mapRef;
    this.map = null;
    this.featureLayer = null;
    this.features = [];
    this.zoomListenerAdded = false;
    this.onFeatureClick = config.onFeatureClick || (() => {});
    this.onFeatureSelect = config.onFeatureSelect || (() => {});
    this.onFeaturesClick = config.onFeaturesClick || (() => {});
    this.onError = config.onError || (() => {});
    this.errors = [];
    this.layers = []; // Initialize layers (adjust based on actual usage)
    this.isInitialized = false; // Khởi tạo là false
    this.eventKey = undefined; // Khởi tạo eventKey
  }

  async getListLayers(): Promise<[]> {
    const resp: [] = await getAllLayer();
    // console.log('resp', resp);
    return resp;
  }

  async initializeMap(): Promise<void> {
    try {
      const listLayers: string[] = await this.getListLayers(); // định nghĩa LayerMeta { id: string; name: string; ... }
      const dynamicLayers: BaseLayer[] = [];

      for (const layerMeta of listLayers) {
        try {
          const data = await getLayer(layerMeta); // lấy GeoJSON từ server

          const vectorLayer = createGeoJSONLayer({
            data,
            style: createLabelAndFillStyle('#77BEF0', '#000000'),
          });

          dynamicLayers.push(vectorLayer);

          // gom tất cả features vào this.features để sau này click kiểm tra
          const features = vectorLayer.getSource()?.getFeatures() ?? [];
          this.features.push(...features);
        } catch (err) {
          console.error(`Không load được layer ${layerMeta}`, err);
          this.errors.push(`Layer ${layerMeta} load thất bại`);
          this.onError(this.errors);
        }
      }

      if (!this.mapRef.current) {
        console.error('Map reference is not available');
        return;
      }

      this.featureLayer = new VectorLayer({
        source: new VectorSource({
          features: [],
        }),
        zIndex: 10,
      });

      this.zoomListenerAdded = false;

      this.map = new Map({
        target: this.mapRef.current,
        layers: [osmLayer, ...dynamicLayers, this.featureLayer],
        view: new View({
          projection: OL_PROJECTION,
          center: fromLonLat(INITIAL_VIEW_CONFIG.center),
          zoom: INITIAL_VIEW_CONFIG.zoom,
          minZoom: INITIAL_VIEW_CONFIG.minZoom,
          maxZoom: INITIAL_VIEW_CONFIG.maxZoom,
        }),
        controls: [],
      });

      this.layers = [osmLayer, ...dynamicLayers, this.featureLayer];

      this.initZoomListener();
      this.isInitialized = true;

      console.log(
        'Map initialized successfully at',
        new Date().toLocaleTimeString(),
      );

      this.map.on('singleclick', (evt: any) => {
        const featuresAtPixel: {
          feature: Feature;
          layer: VectorLayer<VectorSource>;
        }[] = [];

        this.map!.forEachFeatureAtPixel(
          evt.pixel,
          (feature: any, layer: any) => {
            featuresAtPixel.push({ feature, layer });
          },
        );

        if (featuresAtPixel.length === 0) return;

        if (featuresAtPixel.length === 1) {
          const { feature } = featuresAtPixel[0];
          if (this.features.includes(feature)) {
            this.onFeatureClick(feature);
            this.onFeatureSelect(feature, evt.pixel);
            console.log(
              'Feature clicked at',
              new Date().toLocaleTimeString(),
              ':',
              feature.getProperties(),
            );
          }
        } else {
          this.onFeaturesClick(featuresAtPixel.map((f) => f.feature));
        }
      });
    } catch (err) {
      console.error('Lỗi khi khởi tạo bản đồ:', err);
      this.errors.push('Map initialization failed');
      this.onError(this.errors);
    }
  }

  isMapInitialized(): boolean {
    return this.isInitialized;
  }

  initZoomListener() {
    // console.log("initZoomListener: Adding zoom listener"); // Debug
    if (!this.zoomListenerAdded) {
      if (!this.map || !this.map.getView()) {
        console.error('Map or view not initialized in initZoomListener');
        return;
      }
      this.map.getView().on('change:resolution', () => {
        // console.log("change:resolution event triggered"); // Debug
        this.updateFeatureStyles();
      });
      this.zoomListenerAdded = true;
    }
  }
  // Hàm cập nhật style cho tất cả features
  updateFeatureStyles() {
    if (!this.map || !this.map.getView()) {
      console.error('Map or view not initialized in updateFeatureStyles');
      return;
    }
    const currentZoom = this.map.getView().getZoom() ?? 5;
    // console.log(`Updating feature styles with zoom: ${currentZoom}`); // Debug
    this.features.forEach((feature) => {
      const data = feature.get('data') || feature.getProperties();
      const styleConfig = feature.get('styleConfig') || {};
      const featureType = feature.get('type');
      // console.log(
      //   `Updating style for feature type: ${featureType}, data:`,
      //   data,
      //   `styleConfig:`,
      //   styleConfig,
      // ); // Debug

      if (featureType === 'vms') {
        const styles = this.createIconStyle(data, styleConfig, currentZoom);
        feature.setStyle(styles);
      }
    });
  }
  // Hàm tạo style cho feature
  createIconStyle = (
    data: FeatureData,
    styleConfig: StyleConfig,
    zoom: number,
  ): Style[] => {
    const styles: Style[] = [];
    if (styleConfig.icon) {
      const scale = this.calculateScale(zoom);
      // console.log(`Creating icon style with zoom: ${zoom}, scale: ${scale}`); // Debug
      styles.push(
        new Style({
          image: new Icon({
            anchor: [0.5, 30],
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: styleConfig.icon,
            scale, // Use calculated scale
            rotateWithView: false,
            rotation:
              data.bearing && !isNaN(data.bearing)
                ? (data.bearing * Math.PI) / 180
                : 0,
            crossOrigin: 'anonymous',
          }),
        }),
      );
    } else {
      console.warn('No icon provided in styleConfig, skipping icon style'); // Debug
    }

    if (data.text) {
      styles.push(
        new Style({
          text: new Text({
            text: data.text,
            font: styleConfig.font || '14px Arial',
            fill: new Fill({ color: styleConfig.textColor || 'black' }),
            stroke: new Stroke({
              color: styleConfig.textStrokeColor || 'white',
              width: 2,
            }),
            offsetY: styleConfig.textOffsetY || -40,
            textAlign: 'center',
            textBaseline: 'bottom',
          }),
        }),
      );
    }
    return styles;
  };

  addPoint(
    coord: Coordinate,
    data: Record<string, any> = {},
    styleConfig: Record<string, any> = {},
  ) {
    try {
      // Kiểm tra tọa độ hợp lệ
      if (
        !Array.isArray(coord) ||
        coord.length < 2 ||
        typeof coord[0] !== 'number' ||
        typeof coord[1] !== 'number'
      ) {
        throw new Error(
          `Invalid coordinates for Point: ${JSON.stringify(coord)}`,
        );
      }

      // Tạo geometry
      const geometry = new Point(fromLonLat(coord));
      const feature = new Feature({
        geometry,
        type: 'vms', // Explicitly set featureType to 'vms' for scaling
        ...data,
      });

      // Lưu config
      feature.set('styleConfig', styleConfig);
      feature.set('data', data);

      // Lấy zoom hiện tại (fallback 5 nếu map chưa sẵn sàng)
      const currentZoom = this.map?.getView()?.getZoom() ?? 5;
      // console.log(`Adding point with zoom: ${currentZoom}`); // Debug

      // Gán style mặc định
      const styles = this.createIconStyle(data, styleConfig, currentZoom);
      feature.setStyle(styles);

      // Lưu feature
      this.features.push(feature);
      this.featureLayer?.getSource()?.addFeature(feature);
      if (styleConfig.animate) {
        this.animatedMarker(feature, styleConfig.animationConfig);
      }
      // console.log('Point added successfully:', { coord, data, styleConfig });

      return feature;
    } catch (error: any) {
      const message = error?.message || 'Unknown error';
      this.errors.push(message);
      this.onError?.(this.errors);
      console.error('Error adding Point:', message);
      return null;
    }
  }
  animatedMarker = (
    feature: Feature<Point>,
    config: AnimationConfig = {},
  ): void => {
    const {
      duration = 3000,
      maxRadius = 20,
      strokeColor = 'rgba(255, 0, 0, 0.8)',
      strokeWidthBase = 0.25,
    } = config;
    console.log('Starting animatedMarker with config:', config);

    const flashGeom = feature.getGeometry()?.clone() as Point | undefined;
    if (!flashGeom || !this.featureLayer) {
      console.error('Invalid geometry or featureLayer for animation');
      return;
    }

    // Tạo 2 "pha" sóng, mỗi sóng bắt đầu cách nhau duration/2
    const waveCount = 1;
    const waveOffsets = Array.from(
      { length: waveCount },
      (_, i) => (duration / waveCount) * i,
    );
    const start = Date.now();

    const listenerKey: EventsKey = this.featureLayer.on(
      'postrender',
      (event: RenderEvent) => {
        const frameState = event.frameState;
        if (!frameState) return;

        const elapsedTotal = frameState.time - start;
        if (elapsedTotal >= duration * 3) {
          // chạy 2 chu kỳ rồi dừng (bạn có thể bỏ điều kiện này để chạy mãi)
          unByKey(listenerKey);
          return;
        }

        const vectorContext = getVectorContext(event);

        waveOffsets.forEach((offset) => {
          const elapsed =
            (frameState.time - start - offset + duration) % duration;
          const elapsedRatio = elapsed / duration;

          const radius = easeOut(elapsedRatio) * (maxRadius - 5) + 5;
          const opacity = easeOut(1 - elapsedRatio);

          const style = new Style({
            image: new CircleStyle({
              radius,
              stroke: new Stroke({
                color: strokeColor.replace('0.8', opacity.toString()),
                width: strokeWidthBase + opacity,
              }),
            }),
          });

          vectorContext.setStyle(style);
          vectorContext.drawGeometry(flashGeom);
        });

        this.map!.render();
      },
    );
    this.eventKey = listenerKey;
  };

  addPolygon(
    coords: Coordinate[][],
    data: Record<string, any> = {},
    styleConfig: Record<string, any> = {},
  ) {
    try {
      let normalizedCoords: Coordinate[][] | Coordinate[] = coords;

      // Nếu truyền vào là [[ [lon, lat], [lon, lat], ... ]]
      if (
        Array.isArray(coords) &&
        coords.length === 1 &&
        Array.isArray(coords[0]) &&
        (coords[0] as Coordinate[]).every(
          (coord) =>
            Array.isArray(coord) &&
            coord.length === 2 &&
            coord.every((val) => !isNaN(val)),
        )
      ) {
        normalizedCoords = coords[0] as Coordinate[];
      }

      const isMultiPolygon =
        Array.isArray(normalizedCoords) &&
        (normalizedCoords as Coordinate[][]).every(
          (ring) =>
            Array.isArray(ring) &&
            (ring as Coordinate[]).every(
              (coord) =>
                Array.isArray(coord) &&
                coord.length === 2 &&
                coord.every((val) => !isNaN(val)),
            ),
        );

      const isSinglePolygon =
        Array.isArray(normalizedCoords) &&
        (normalizedCoords as Coordinate[]).every(
          (coord) =>
            Array.isArray(coord) &&
            coord.length === 2 &&
            coord.every((val) => !isNaN(val)),
        );

      if (!isMultiPolygon && !isSinglePolygon) {
        throw new Error(
          `Invalid coordinates for Polygon/MultiPolygon: ${JSON.stringify(
            coords,
          )}`,
        );
      }

      if (isSinglePolygon && (normalizedCoords as Coordinate[]).length < 3) {
        throw new Error(
          `Polygon must have at least 3 coordinates: ${JSON.stringify(coords)}`,
        );
      }

      if (
        isMultiPolygon &&
        (normalizedCoords as Coordinate[][]).some((ring) => ring.length < 3)
      ) {
        throw new Error(
          `Each ring in MultiPolygon must have at least 3 coordinates: ${JSON.stringify(
            coords,
          )}`,
        );
      }

      let geometry: Polygon | MultiPolygon;
      if (isMultiPolygon) {
        const transformedCoords = (normalizedCoords as Coordinate[][]).map(
          (ring) => ring.map(([lon, lat]) => fromLonLat([lon, lat])),
        );
        geometry = new MultiPolygon([transformedCoords]);
      } else {
        const transformedCoords = (normalizedCoords as Coordinate[]).map(
          ([lon, lat]) => fromLonLat([lon, lat]),
        );
        geometry = new Polygon([transformedCoords]);
      }

      const feature = new Feature<Polygon | MultiPolygon>({
        geometry,
        ...data,
      });

      feature.set('styleConfig', styleConfig);
      feature.set('data', data);
      feature.set('type', 'polygon');

      // Nếu bạn có sẵn hàm tạo style theo zoom
      const currentZoom = this.map?.getView().getZoom();
      feature.setStyle(
        this.createPolygonStyle(data, styleConfig, currentZoom || 5),
      );

      this.features.push(feature);
      this.featureLayer?.getSource()?.addFeature(feature);

      return feature;
    } catch (error) {
      this.errors.push('Error adding Polygon: ' + (error as Error).message);
      this.onError?.(this.errors);
      console.error('Error adding Polygon:', (error as Error).message);
      return null;
    }
  }

  // Hàm addLineString đã được sửa đổi
  addLineString(
    coords: Coordinate[],
    data: FeatureData = {},
    styleConfig: StyleConfig = {},
  ): Feature | null {
    try {
      // Kiểm tra coords là mảng hợp lệ và có ít nhất 2 tọa độ
      if (
        !Array.isArray(coords) ||
        coords.length < 2 ||
        !coords.every(
          (coord) =>
            Array.isArray(coord) &&
            coord.length === 2 &&
            typeof coord[0] === 'number' &&
            typeof coord[1] === 'number',
        )
      ) {
        throw new Error(
          `Invalid coordinates for LineString: ${JSON.stringify(coords)}`,
        );
      }

      // Chuyển đổi tọa độ từ [lon, lat] sang hệ tọa độ của OpenLayers
      const transformedCoords = coords.map((coord) => fromLonLat(coord));
      const geometry = new LineString(transformedCoords);
      const feature = new Feature({
        geometry,
        ...data,
      });

      // Tạo style cho LineString
      const style = new Style({
        text: new Text({
          text: data.text || '',
          font: styleConfig.font || '16px Arial', // Tăng kích thước font
          fill: new Fill({ color: styleConfig.textColor || 'black' }), // Đổi màu thành đen để nổi bật
          stroke: new Stroke({
            color: styleConfig.textStrokeColor || 'white',
            width: 2, // Tăng độ rộng viền
          }),
          placement: 'line',
          textAlign: 'center',
          textBaseline: 'middle', // Đổi thành 'middle' để căn giữa theo chiều dọc
          offsetY: styleConfig.textOffsetY || -10, // Dịch text lên trên một chút
        }),
        stroke: new Stroke({
          color: styleConfig.strokeColor || 'blue',
          width: styleConfig.strokeWidth || 5,
        }),
      });

      feature.setStyle(style);

      // Thêm feature vào features và featureLayer
      if (this.featureLayer && this.isInitialized) {
        this.features.push(feature);
        this.featureLayer.getSource()?.addFeature(feature);
        // console.log(
        //   'LineString added successfully at',
        //   new Date().toLocaleTimeString(),
        //   ':',
        //   { coords, data, styleConfig },
        // );
        // Đảm bảo bản đồ được render lại
        this.map?.render();
        return feature;
      } else {
        throw new Error('featureLayer or map is not initialized');
      }
    } catch (error: any) {
      this.errors.push(error.message);
      this.onError(this.errors);
      console.error(
        'Error adding LineString at',
        new Date().toLocaleTimeString(),
        ':',
        error.message,
      );
      return null;
    }
  }

  createPolygonStyle = (
    data: Record<string, any> = {},
    styleConfig: Record<string, any> = {},
    zoom: number,
  ) => {
    // console.log(
    //   `createPolygonStyle called with zoom: ${zoom}, styleConfig:`,
    //   styleConfig,
    // ); // Debug
    const textContent = `Tên: ${data?.name ?? 'Chưa có'}\n\n Loại: ${
      data?.type ?? 0
    }\n\nThông tin: ${data?.description ?? 'Chưa có'}`;

    const textStyle = new Text({
      text: textContent,
      font: styleConfig.font || '14px Arial',
      fill: new Fill({ color: styleConfig.textColor || 'black' }),
      stroke: new Stroke({
        color: styleConfig.textStrokeColor || 'white',
        width: 1,
      }),
      offsetY: styleConfig.textOffsetY || -40,
      textAlign: 'center',
      textBaseline: 'bottom',
    });

    // Điều chỉnh fillColor dựa trên zoom (tùy chọn)
    let fillColor = styleConfig.fillColor || 'rgba(255,0,0,0.3)';
    // Nếu muốn tăng độ đậm của fill khi zoom gần
    if (zoom > 10) {
      fillColor = styleConfig.fillColor
        ? styleConfig.fillColor.replace(/,[\d.]*\)/, ',0.5)') // Tăng độ đậm
        : 'rgba(255,0,0,0.5)';
    }

    const style = new Style({
      stroke: new Stroke({
        color: styleConfig.borderColor || 'red',
        width: styleConfig.borderWidth || 2,
      }),
      fill: new Fill({
        color: fillColor,
      }),
      text: textStyle,
    });

    // console.log(`Polygon style created:`, style); // Debug
    return [style];
  };

  private calculateScale = (zoom: number): number => {
    // console.log(`calculateScale called with zoom: ${zoom}`); // Debug
    const minZoom = INITIAL_VIEW_CONFIG.minZoom; // Zoom tối thiểu
    const maxZoom = INITIAL_VIEW_CONFIG.maxZoom; // Zoom tối đa
    const minScale = INITIAL_VIEW_CONFIG.minScale; // Scale nhỏ nhất
    const maxScale = INITIAL_VIEW_CONFIG.maxScale; // Scale lớn nhất
    const clampedZoom = Math.min(Math.max(zoom, minZoom), maxZoom);
    const scale =
      minScale +
      ((clampedZoom - minZoom) / (maxZoom - minZoom)) * (maxScale - minScale);
    // console.log(`Calculated scale: ${scale}`); // Debug
    return scale;
  };

  zoomToFeatures(): void {
    if (!this.map) {
      console.error('Map is not initialized');
      return;
    }

    if (this.features.length === 0) {
      this.map.getView().animate({
        center: fromLonLat(INITIAL_VIEW_CONFIG.center),
        zoom: INITIAL_VIEW_CONFIG.zoom,
        duration: 500,
      });
      return;
    }

    let extent: Extent = createEmpty();
    this.features.forEach((feature, index) => {
      try {
        const featureExtent = feature.getGeometry()?.getExtent();
        if (featureExtent && !isEmpty(featureExtent)) {
          extent = extend(extent, featureExtent);
        } else {
          this.errors.push(`Empty extent for feature at index ${index}`);
        }
      } catch (error) {
        this.errors.push(
          `Error getting extent for feature at index ${index}: ${
            (error as Error).message
          }`,
        );
      }
    });

    if (!isEmpty(extent)) {
      this.map.getView().fit(extent, {
        padding: [300, 300, 300, 300],
        maxZoom: 12,
        duration: 500,
        callback: () => {
          this.updateFeatureStyles();
        },
      });
    } else {
      this.errors.push('No valid features to zoom to.');
    }

    if (this.errors.length > 0) {
      this.onError(this.errors);
      console.error(
        'Zoom errors at',
        new Date().toLocaleTimeString(),
        ':',
        this.errors,
      );
    }
  }

  flyToFeature(
    feature: Feature | Feature[],
    done: (complete: boolean) => void = () => {},
  ): void {
    if (!this.map) {
      console.error('Map is not initialized');
      return;
    }

    const features = Array.isArray(feature) ? feature : [feature];

    if (!features || features.length === 0) {
      this.errors.push('No feature provided for flyToFeature');
      this.onError(this.errors);
      console.error(
        'Fly to feature error at',
        new Date().toLocaleTimeString(),
        ': No feature provided',
      );
      return;
    }

    const view = this.map.getView();
    let extent: Extent = createEmpty();
    const validFeatures: Feature[] = [];

    features.forEach((f, index) => {
      if (f && typeof f.getGeometry === 'function') {
        const featureExtent = f.getGeometry()?.getExtent();
        if (featureExtent && !isEmpty(featureExtent)) {
          extent = extend(extent, featureExtent);
          validFeatures.push(f);
        } else {
          this.errors.push(`Empty extent for feature at index ${index}`);
        }
      } else {
        this.errors.push(`Invalid feature at index ${index}`);
      }
    });

    if (isEmpty(extent)) {
      this.errors.push('Empty extent for selected features');
      this.onError(this.errors);
      console.error(
        'Fly to feature error at',
        new Date().toLocaleTimeString(),
        ': Empty extent',
      );
      return;
    }

    const duration = 1000;
    const zoom = view.getZoom() || 5;
    let parts = 2;
    let called = false;

    const callback = (complete: boolean) => {
      parts--;
      if (called) {
        return;
      }
      if (parts === 0 || !complete) {
        called = true;
        this.updateFeatureStyles();
        done(complete);
      }
    };

    view.fit(extent, {
      padding: [300, 300, 300, 300],
      maxZoom: features.length === 1 ? 8 : 10,
      duration,
    });

    view.animate(
      {
        zoom: zoom - 1,
        duration: duration / 2,
      },
      {
        zoom: 14,
        duration: duration / 2,
      },
      callback,
    );
  }

  destroy(): void {
    if (this.map) {
      this.map.setTarget(undefined);
      this.isInitialized = false;
      console.log('Map destroyed at', new Date().toLocaleTimeString());
    }
  }
}

export { MapManager };
