package com.grigowashere.aismap.view;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.grigowashere.aismap.R;
import com.grigowashere.aismap.models.Vessel;
 import com.grigowashere.aismap.models.AISVessel;

/**
 * Overlay для отображения курсора на карте с координатами и информацией о расстоянии
 */
public class CursorOverlay {
    
    private Context context;
    private View overlayView;
    private TextView tvCursorLatitude;
    private TextView tvCursorLongitude;
    private TextView tvDistance;
    private TextView tvBearing;
    private LinearLayout coordinatesPanel;
    private LinearLayout distanceBearingPanel;
    private LinearLayout aisVesselInfoPanel;
    
    // AIS vessel info TextViews
    private TextView tvAisMmsi;
    private TextView tvAisName;
    private TextView tvAisCallSign;
    private TextView tvAisCog;
    private TextView tvAisSog;
    
    private Vessel ownVessel;
    private AISVessel currentAisVessel;
    private double cursorLatitude;
    private double cursorLongitude;
    
    public CursorOverlay(Context context) {
        this.context = context;
        initializeViews();
    }
    
    private void initializeViews() {
        LayoutInflater inflater = LayoutInflater.from(context);
        overlayView = inflater.inflate(R.layout.cursor, null);
        
        tvCursorLatitude = overlayView.findViewById(R.id.tv_cursor_latitude);
        tvCursorLongitude = overlayView.findViewById(R.id.tv_cursor_longitude);
        tvDistance = overlayView.findViewById(R.id.tv_distance);
        tvBearing = overlayView.findViewById(R.id.tv_bearing);
        coordinatesPanel = overlayView.findViewById(R.id.coordinates_panel);
        distanceBearingPanel = overlayView.findViewById(R.id.distance_bearing_panel);
        aisVesselInfoPanel = overlayView.findViewById(R.id.ais_vessel_info_panel);
        
        // Initialize AIS vessel info TextViews
        tvAisMmsi = overlayView.findViewById(R.id.tv_ais_mmsi);
        tvAisName = overlayView.findViewById(R.id.tv_ais_name);
        tvAisCallSign = overlayView.findViewById(R.id.tv_ais_call_sign);
        tvAisCog = overlayView.findViewById(R.id.tv_ais_cog);
        tvAisSog = overlayView.findViewById(R.id.tv_ais_sog);
        
        // По умолчанию курсор скрыт
        overlayView.setVisibility(View.GONE);
    }
    
    public View getView() {
        return overlayView;
    }
    
    /**
     * Обновляет координаты курсора (центра экрана)
     */
    public void updateCursorCoordinates(double latitude, double longitude) {
        this.cursorLatitude = latitude;
        this.cursorLongitude = longitude;
        
        tvCursorLatitude.setText(String.format("%.6f°", latitude));
        tvCursorLongitude.setText(String.format("%.6f°", longitude));
        
        // Обновляем информацию о расстоянии и пеленге, если есть данные о нашем судне
        updateDistanceAndBearing();
    }
    
    /**
     * Устанавливает данные о нашем судне для расчета расстояния и пеленга
     */
    public void setOwnVessel(Vessel vessel) {
        this.ownVessel = vessel;
        updateDistanceAndBearing();
    }
    
    /**
     * Обновляет информацию о расстоянии и пеленге
     */
    private void updateDistanceAndBearing() {
        if (ownVessel != null && isValidPosition(ownVessel)) {
            double distance = calculateDistance(
                ownVessel.getLatitude(), ownVessel.getLongitude(),
                cursorLatitude, cursorLongitude
            );
            
            // Вычисляем пеленг от судна к курсору
            double bearingToCursor = calculateBearing(
                ownVessel.getLatitude(), ownVessel.getLongitude(),
                cursorLatitude, cursorLongitude
            );
            
            // Вычисляем относительный пеленг (на сколько градусов повернуть от курса судна)
            double relativeBearing;
            if (ownVessel.getCourse() > 0) {
                // Пеленг относительно курса судна
                relativeBearing = bearingToCursor - ownVessel.getCourse();
                // Нормализуем в диапазон -180..+180
                while (relativeBearing > 180) relativeBearing -= 360;
                while (relativeBearing < -180) relativeBearing += 360;
            } else {
                // Если курс неизвестен, показываем абсолютный пеленг
                relativeBearing = bearingToCursor;
            }
            
            // Форматируем расстояние: в км с дробной частью если > 1000м, иначе в метрах
            String distanceText;
            if (distance >= 1000) {
                distanceText = String.format("Rng: %.2f км", distance / 1000.0);
            } else {
                distanceText = String.format("Rng: %.1f м", distance);
            }
            
            tvDistance.setText(distanceText);
            tvBearing.setText(String.format("Brg: %.1f°", relativeBearing));
            
            // Показываем информацию о расстоянии и пеленге
            tvDistance.setVisibility(View.VISIBLE);
            tvBearing.setVisibility(View.VISIBLE);
        } else {
            // Скрываем информацию, если нет валидных координат нашего судна
            tvDistance.setVisibility(View.GONE);
            tvBearing.setVisibility(View.GONE);
        }
    }
    
    /**
     * Вычисляет расстояние между двумя точками в метрах (формула гаверсинуса)
     */
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int R = 6371000; // Радиус Земли в метрах
        
        double lat1Rad = Math.toRadians(lat1);
        double lat2Rad = Math.toRadians(lat2);
        double deltaLatRad = Math.toRadians(lat2 - lat1);
        double deltaLonRad = Math.toRadians(lon2 - lon1);
        
        double a = Math.sin(deltaLatRad / 2) * Math.sin(deltaLatRad / 2) +
                Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                Math.sin(deltaLonRad / 2) * Math.sin(deltaLonRad / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return R * c;
    }
    
    /**
     * Вычисляет пеленг от первой точки ко второй в градусах
     */
    private double calculateBearing(double lat1, double lon1, double lat2, double lon2) {
        double lat1Rad = Math.toRadians(lat1);
        double lat2Rad = Math.toRadians(lat2);
        double deltaLonRad = Math.toRadians(lon2 - lon1);
        
        double y = Math.sin(deltaLonRad) * Math.cos(lat2Rad);
        double x = Math.cos(lat1Rad) * Math.sin(lat2Rad) -
                Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(deltaLonRad);
        
        double bearing = Math.toDegrees(Math.atan2(y, x));
        return (bearing + 360) % 360; // Нормализуем в диапазон 0-360
    }
    
    /**
     * Скрывает курсор
     */
    public void hideCursor() {
        if (overlayView != null) {
            overlayView.setVisibility(View.GONE);
        }
    }
    
    /**
     * Показывает курсор
     */
    public void showCursor() {
        if (overlayView != null) {
            overlayView.setVisibility(View.VISIBLE);
        }
    }
    
    /**
     * Устанавливает информацию об AIS судне под курсором
     */
    public void setAisVesselInfo(AISVessel vessel) {
        this.currentAisVessel = vessel;
        updateAisVesselInfo();
    }
    
    /**
     * Обновляет отображение информации об AIS судне
     */
    private void updateAisVesselInfo() {
        if (currentAisVessel != null) {
            // MMSI
            tvAisMmsi.setText("MMSI: " + currentAisVessel.getMmsi());
            
            // Название
            String name = currentAisVessel.getVesselName();
            if (name != null && !name.trim().isEmpty()) {
                tvAisName.setText("Название: " + name);
                tvAisName.setVisibility(View.VISIBLE);
            } else {
                tvAisName.setVisibility(View.GONE);
            }
            
            // Позывной
            String callSign = currentAisVessel.getCallSign();
            if (callSign != null && !callSign.trim().isEmpty()) {
                tvAisCallSign.setText("Позывной: " + callSign);
                tvAisCallSign.setVisibility(View.VISIBLE);
            } else {
                tvAisCallSign.setVisibility(View.GONE);
            }
            
            // COG (курс)
            if (currentAisVessel.getCourse() > 0) {
                tvAisCog.setText(String.format("COG: %.1f°", currentAisVessel.getCourse()));
                tvAisCog.setVisibility(View.VISIBLE);
            } else {
                tvAisCog.setVisibility(View.GONE);
            }
            
            // SOG (скорость)
            if (currentAisVessel.getSpeed() > 0) {
                tvAisSog.setText(String.format("SOG: %.1f уз", currentAisVessel.getSpeed()));
                tvAisSog.setVisibility(View.VISIBLE);
            } else {
                tvAisSog.setVisibility(View.GONE);
            }
            
            // Показываем панель
            aisVesselInfoPanel.setVisibility(View.VISIBLE);
        } else {
            // Скрываем панель
            aisVesselInfoPanel.setVisibility(View.GONE);
        }
    }
    
    /**
     * Очищает информацию об AIS судне
     */
    public void clearAisVesselInfo() {
        this.currentAisVessel = null;
        aisVesselInfoPanel.setVisibility(View.GONE);
    }
    
    /**
     * Проверяет валидность позиции судна
     */
    private boolean isValidPosition(Vessel vessel) {
        if (vessel == null) return false;
        
        double lat = vessel.getLatitude();
        double lon = vessel.getLongitude();
        
        // Проверяем, что координаты в допустимых пределах
        return lat >= -90 && lat <= 90 && lon >= -180 && lon <= 180 &&
               lat != 0.0 && lon != 0.0; // Исключаем нулевые координаты
    }
}
