package com.grigowashere.aismap.maps;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.view.View;

import com.grigowashere.aismap.models.Vessel;
import com.grigowashere.aismap.models.AISVessel;
import com.yandex.mapkit.Animation;
import com.yandex.mapkit.geometry.Point;
import com.yandex.mapkit.map.CameraPosition;
import com.yandex.mapkit.map.MapObjectCollection;
import com.yandex.mapkit.mapview.MapView;
import com.yandex.runtime.image.ImageProvider;

import java.util.HashMap;
import java.util.Map;

/**
 * Реализация карты для Яндекс.Карт
 * Использует новый менеджер маркеров для предотвращения финализации объектов
 */
public class YandexMapImpl implements MapInterface {
    
    private Context context;
    private MapView mapView;
    private MapObjectCollection mapObjects;
    private MarkerClickListener markerClickListener;
    
    // Новый менеджер маркеров
    private YandexMarkerManager markerManager;
    
    // Слушатель поворота карты
    private com.yandex.mapkit.map.InputListener inputListener;
    private float lastMapAzimuth = 0.0f;
    
    public YandexMapImpl(Context context, MapView mapView) {
        this.context = context;
        this.mapView = mapView;
        
        // Получение коллекции объектов карты
        try {
            this.mapObjects = mapView.getMap().getMapObjects().addCollection();
            // Инициализируем менеджер маркеров
            com.grigowashere.aismap.utils.SettingsManager settingsManager = 
                new com.grigowashere.aismap.utils.SettingsManager(context);
            this.markerManager = new YandexMarkerManager(context, mapObjects, mapView, settingsManager);
        } catch (Exception e) {
            // Ошибка создания коллекции объектов карты
        }
    }
    
    @Override
    public void initialize() {
        // Инициализируем слушатель поворота карты
        setupCameraListener();
        
        // Инициализируем менеджер маркеров
        if (markerManager != null) {
            markerManager.initialize();
        }
    }
    
    
    @Override
    public void cleanup() {
        // Очищаем менеджер маркеров
        if (markerManager != null) {
            markerManager.cleanup();
        }
        
        // Удаляем слушатель ввода
        if (inputListener != null && mapView != null) {
            mapView.getMap().removeInputListener(inputListener);
        }
        
        if (mapObjects != null) {
            mapView.getMap().getMapObjects().remove(mapObjects);
        }
        if (mapView != null) {
            mapView.onStop();
        }
    }
    
    @Override
    public void addOwnVesselMarker(Vessel vessel) {
        if (markerManager != null) {
            markerManager.updateOwnVesselMarker(vessel);
        }
    }
    
    @Override
    public void updateOwnVesselPosition(Vessel vessel) {
        if (markerManager != null) {
            markerManager.updateOwnVesselMarker(vessel);
        }
    }
    
    @Override
    public void addAISVesselMarker(AISVessel vessel) {
        if (markerManager != null) {
            markerManager.updateAISVesselMarker(vessel);
        }
    }
    
    @Override
    public void updateAISVesselPosition(AISVessel vessel) {
        if (markerManager != null) {
            markerManager.updateAISVesselMarker(vessel);
        }
    }
    
    @Override
    public void removeAISVesselMarker(String mmsi) {
        if (markerManager != null) {
            markerManager.removeAISVesselMarker(mmsi);
        }
    }
    
    @Override
    public void clearAISVesselMarkers() {
        if (markerManager != null) {
            markerManager.clearAISVesselMarkers();
        }
    }
    
    @Override
    public void centerOnPosition(double latitude, double longitude) {
        Point point = new Point(latitude, longitude);
        CameraPosition cameraPosition = new CameraPosition(point, 13.0f, 0.0f, 0.0f);
        mapView.getMap().move(cameraPosition, new Animation(Animation.Type.SMOOTH, 1.0f), null);
    }
    
    @Override
    public void setZoom(float zoom) {
        CameraPosition currentPosition = mapView.getMap().getCameraPosition();
        Point target = currentPosition.getTarget();
        CameraPosition newPosition = new CameraPosition(target, zoom, currentPosition.getAzimuth(), currentPosition.getTilt());
        mapView.getMap().move(newPosition, new Animation(Animation.Type.SMOOTH, 0.5f), null);
    }
    
    @Override
    public float getZoom() {
        return mapView.getMap().getCameraPosition().getZoom();
    }
    
    @Override
    public void addLayer(String layerId, Object layerData) {
        // Реализация добавления дополнительных слоев
        // Зависит от конкретных требований
    }
    
    @Override
    public void removeLayer(String layerId) {
        // Реализация удаления слоев
    }
    
    @Override
    public void setMarkerClickListener(MarkerClickListener listener) {
        this.markerClickListener = listener;
        
        // Устанавливаем обработчик в менеджере маркеров
        if (markerManager != null) {
            markerManager.setMarkerClickListener(listener);
        }
    }
    
    /**
     * Обновляет обработчики кликов для всех существующих маркеров
     * Этот метод переустанавливает обработчики для всех маркеров
     */
    public void refreshMarkerClickListeners() {
        if (markerManager != null) {
            markerManager.checkAndRestoreMarkers();
        }
    }
    
    /**
     * Перерисовывает все маркеры с учетом текущего азимута карты
     * Вызывается при повороте карты
     */
    public void refreshAllMarkers() {
        if (markerManager != null) {
            markerManager.refreshAllMarkers();
        }
    }
    
    /**
     * Обновляет все маркеры при повороте карты
     * Вызывается из слушателя поворота карты
     */
    public void onMapRotationChanged() {
        if (markerManager != null) {
            markerManager.refreshAllMarkers();
        }
    }
    
    /**
     * Принудительно обновляет все маркеры
     * Можно вызывать извне для обновления маркеров
     */
    public void forceRefreshMarkers() {
        if (markerManager != null) {
            markerManager.refreshAllMarkers();
        }
    }
    
    /**
     * Принудительно обновляет все маркеры при изменении зума
     */
    public void forceRefreshMarkersOnZoomChange() {
        if (markerManager != null) {
            markerManager.forceRefreshAllMarkers();
        }
    }
    
    /**
     * Проверяет и восстанавливает финализированные маркеры
     */
    public void checkAndRestoreMarkers() {
        if (markerManager != null) {
            markerManager.checkAndRestoreMarkers();
        }
    }
    
    /**
     * Получает количество активных маркеров
     */
    public int getActiveMarkerCount() {
        if (markerManager != null) {
            return markerManager.getActiveMarkerCount();
        }
        return 0;
    }
    
    /**
     * Включает/выключает отображение путей движения
     */
    public void setPathTrackingEnabled(boolean enabled) {
        if (markerManager != null) {
            markerManager.setPathTrackingEnabled(enabled);
        }
    }
    
    /**
     * Очищает путь конкретного судна
     */
    public void clearVesselPath(String mmsi) {
        if (markerManager != null) {
            markerManager.clearVesselPath(mmsi);
        }
    }
    
    /**
     * Очищает все пути движения
     */
    public void clearAllPaths() {
        if (markerManager != null) {
            markerManager.clearAllPaths();
        }
    }
    
    /**
     * Обновляет настройки отображения путей
     */
    public void updatePathSettings(int pathColor, int predictionColor, float pathWidth, float predictionWidth) {
        if (markerManager != null) {
            markerManager.updatePathSettings(pathColor, predictionColor, pathWidth, predictionWidth);
        }
    }
    
    
    /**
     * Получение MapView для использования в layout
     */
    public MapView getMapView() {
        return mapView;
    }
    
    /**
     * Настройка слушателя поворота карты
     */
    private void setupCameraListener() {
        try {
            inputListener = new com.yandex.mapkit.map.InputListener() {
                @Override
                public void onMapTap(com.yandex.mapkit.map.Map map, com.yandex.mapkit.geometry.Point point) {
                    // Не обрабатываем клики по карте
                }
                
                @Override
                public void onMapLongTap(com.yandex.mapkit.map.Map map, com.yandex.mapkit.geometry.Point point) {
                    // Не обрабатываем долгие клики по карте
                }
            };
            
            // Добавляем слушатель к карте
            mapView.getMap().addInputListener(inputListener);
            
            // Включаем жесты поворота карты
            mapView.getMap().setRotateGesturesEnabled(true);
            
            // Добавляем слушатель изменений камеры для обновления маркеров при повороте и зуме
            mapView.getMap().addCameraListener(new com.yandex.mapkit.map.CameraListener() {
                private long lastUpdateTime = 0;
                private static final long UPDATE_THROTTLE = 200; // 200мс между обновлениями (увеличено для снижения нагрузки)
                private float lastZoom = -1;
                
                @Override
                public void onCameraPositionChanged(com.yandex.mapkit.map.Map map, 
                    com.yandex.mapkit.map.CameraPosition cameraPosition, 
                    com.yandex.mapkit.map.CameraUpdateReason reason, 
                    boolean finished) {
                    
                    // Обновляем маркеры в реальном времени с throttling
                    long currentTime = System.currentTimeMillis();
                    float currentZoom = cameraPosition.getZoom();
                    
                    // Проверяем, изменился ли зум значительно (больше чем на 1.0)
                    boolean zoomChanged = Math.abs(currentZoom - lastZoom) > 1.0f;
                    
                    if (currentTime - lastUpdateTime >= UPDATE_THROTTLE || zoomChanged) {
                        //onMapRotationChanged();
                        // Обновляем маркеры только при значительных изменениях
                        if (zoomChanged) {
                            // При изменении зума принудительно обновляем все маркеры
                            forceRefreshMarkersOnZoomChange();
                        } else {
                            // При повороте только проверяем валидность маркеров
                            checkAndRestoreMarkers();
                        }
                        lastUpdateTime = currentTime;
                        lastZoom = currentZoom;
                    }
                }
            });
            
            // Добавляем дополнительный слушатель для жестов поворота
            mapView.getMap().addInputListener(new com.yandex.mapkit.map.InputListener() {
                private long lastGestureTime = 0;
                private static final long GESTURE_THROTTLE = 100; // 100мс между обновлениями
                
                @Override
                public void onMapTap(com.yandex.mapkit.map.Map map, com.yandex.mapkit.geometry.Point point) {
                    // Не обрабатываем клики по карте
                }
                
                @Override
                public void onMapLongTap(com.yandex.mapkit.map.Map map, com.yandex.mapkit.geometry.Point point) {
                    // Не обрабатываем долгие клики по карте
                }
            });
        } catch (Exception e) {
            // Ошибка установки слушателя
        }
    }
    
}
