package com.grigowashere.aismap.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;

import com.grigowashere.aismap.models.AISVessel;
import com.grigowashere.aismap.models.Vessel;
import com.grigowashere.aismap.utils.GeoUtils;

import java.util.ArrayList;
import java.util.List;

public class CompassView extends BaseDockWidget {
    private static final String TAG = "CompassView";
    
    private float targetAzimuth = 0;
    private float currentAzimuth = 0;
    private float magneticCompass = 0; // магнитный компас
    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint vesselPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Path vesselPath = new Path();
    private final String[] directions = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
    private float centerX;
    private float centerY;
    private static final float SMOOTHING_FACTOR = 0.15f;
    private List<AISVessel> nearbyVessels = new ArrayList<>();
    private Vessel ourVessel; // наше судно для расчета расстояний
    private static final float MAX_DISPLAY_DISTANCE = 10000; // 10 км
    private static final float MIN_VESSEL_SIZE = 10; // минимальный размер значка
    private static final float MAX_VESSEL_SIZE = 30; // максимальный размер значка

    public CompassView(Context context) {
        super(context);
        init();
    }

    public CompassView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint.setColor(Color.WHITE);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setTextSize(36f);

        vesselPaint.setStyle(Paint.Style.FILL);
        vesselPaint.setAntiAlias(true);
        
        // Устанавливаем фон для видимости
        setBackgroundColor(Color.argb(200, 0, 0, 0));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w / 2f;
        centerY = h / 2f;
    }

    private float getShortestRotation(float start, float end) {
        // Нормализуем углы к диапазону 0-360
        start = normalizeAngle(start);
        end = normalizeAngle(end);
        
        float diff = end - start;
        
        // Если разность больше 180°, идем в обратную сторону
        if (diff > 180) {
            diff -= 360;
        } else if (diff < -180) {
            diff += 360;
        }
        
        return diff;
    }
    
    private float normalizeAngle(float angle) {
        while (angle < 0) angle += 360;
        while (angle >= 360) angle -= 360;
        return angle;
    }



    // Прямая шкала (dock-режим)
    @Override
    protected void onDrawDock(Canvas canvas) {
       // Log.d(TAG, "onDrawDock called, width=" + getWidth() + ", height=" + getHeight());
        
        float w = getWidth();
        float h = getHeight();
        
        if (w <= 0 || h <= 0) {
            Log.w(TAG, "Invalid dimensions: width=" + w + ", height=" + h);
            return;
        }
        
        // Простой фон для начала
        paint.setColor(Color.argb(200, 0, 0, 0));
        canvas.drawRect(0, 0, w, h, paint);
        
        // Масштабируем размеры в зависимости от высоты виджета
        float baseHeight = dp(80); // базовая высота
        float scaleFactor = Math.max(0.8f, Math.min(2.0f, h / baseHeight));
        
        // Простой текст для проверки
        paint.setColor(Color.WHITE);
        paint.setTextSize(24 * scaleFactor);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText("КОМПАС", w/2, h/2, paint);
        canvas.drawText("Азимут: " + (int)currentAzimuth + "°", w/2, h/2 + 30 * scaleFactor, paint);
        canvas.drawText("Магн: " + (int)magneticCompass + "°", w/2, h/2 + 60 * scaleFactor, paint);
        
        // Плавное обновление азимута
        float diff = getShortestRotation(currentAzimuth, targetAzimuth);
        if (Math.abs(diff) > 0.1f) {
            // Ограничиваем максимальное изменение за один кадр
            float maxChange = 3.0f; // максимальное изменение в градусах за кадр
            float change = Math.signum(diff) * Math.min(Math.abs(diff * SMOOTHING_FACTOR), maxChange);
            currentAzimuth += change;
            currentAzimuth = normalizeAngle(currentAzimuth);
            postInvalidateOnAnimation();
        }
        
        // Рисуем простую шкалу
        float centerX = w / 2f;
        float centerY = h / 2f;
        float visibleDegrees = 120;
        
        // Рисуем деления шкалы
        for (int degree = 0; degree < 360; degree += 15) {
            // Вычисляем относительное положение деления
            float relativeDegree = getShortestRotation(currentAzimuth, degree);
            
            // Рисуем только видимые деления
            if (Math.abs(relativeDegree) <= visibleDegrees / 2) {
                float x = centerX + (relativeDegree / (visibleDegrees / 2)) * (w / 2);
                float lineHeight = (degree % 30 == 0) ? 20 * scaleFactor : 10 * scaleFactor;
                canvas.drawLine(x, centerY - lineHeight, x, centerY + lineHeight, paint);
                
                if (degree % 30 == 0) {
                    String degreeText = String.valueOf(degree);
                    paint.setTextSize(16 * scaleFactor);
                    canvas.drawText(degreeText, x, centerY - 30 * scaleFactor, paint);
                }
                if (degree % 45 == 0) {
                    int directionIndex = (degree / 45) % 8;
                    if (directionIndex < directions.length) {
                        paint.setTextSize(18 * scaleFactor);
                        canvas.drawText(directions[directionIndex], x, centerY + 50 * scaleFactor, paint);
                    }
                }
            }
        }
        
        // Рисуем суда
        for (AISVessel vessel : nearbyVessels) {
            float relativeBearing = getShortestRotation(currentAzimuth, (float) vessel.getCourse());
            if (Math.abs(relativeBearing) <= visibleDegrees / 2) {
                float x = centerX + (relativeBearing / (visibleDegrees / 2)) * (w / 2);
                double distance = ourVessel != null ? GeoUtils.calculateDistance(ourVessel, vessel) : 0;
                float size = calculateVesselSize((float) distance) * scaleFactor;
                vesselPaint.setColor(getVesselColor(vessel));
                drawVesselTriangle(canvas, x, centerY, size, (float) (vessel.getCourse() - currentAzimuth));
            }
        }
        
        // Центральная линия (направление вперёд)
        paint.setColor(Color.RED);
        paint.setStrokeWidth(3 * scaleFactor);
        canvas.drawLine(centerX, centerY - h/2, centerX, centerY + h/2, paint);
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(1);
        
        // Выделяем зону resize в зависимости от позиции закрепления
        if (isDocked) {
            Paint resizePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            resizePaint.setColor(Color.argb(120, 255, 255, 255));
            resizePaint.setStyle(Paint.Style.STROKE);
            resizePaint.setStrokeWidth(2);
            
            paint.setTextSize(12);
            paint.setColor(Color.WHITE);
            
            if (isDockTop()) {
                // Если закреплен сверху, показываем зону resize снизу
                canvas.drawRect(0, h - dp(24), w, h, resizePaint);
                canvas.drawText("↕", w/2, h - dp(12), paint);
            } else {
                // Если закреплен снизу, показываем зону resize сверху
                canvas.drawRect(0, 0, w, dp(24), resizePaint);
                canvas.drawText("↕", w/2, dp(12), paint);
            }
        }
    }

    // Круглый компас (draggable-режим)
    @Override
    protected void onDrawCircle(Canvas canvas) {
        //Log.d(TAG, "onDrawCircle called, width=" + getWidth() + ", height=" + getHeight());
        
        float w = getWidth();
        float h = getHeight();
        
        if (w <= 0 || h <= 0) {
           // Log.w(TAG, "Invalid dimensions: width=" + w + ", height=" + h);
            return;
        }
        
        float cx = w / 2f;
        float cy = h / 2f;
        float radius = Math.min(w, h) / 2f * 0.9f;
        
        // Масштабируем размеры в зависимости от размера виджета
        float baseSize = dp(120); // базовая высота
        float scaleFactor = Math.max(0.8f, Math.min(2.0f, Math.min(w, h) / baseSize));
        
        // Фон
        paint.setColor(Color.argb(200, 0, 0, 0));
        canvas.drawCircle(cx, cy, radius, paint);
        paint.setColor(Color.WHITE);
        
        // Плавное обновление азимута
        float diff = getShortestRotation(currentAzimuth, targetAzimuth);
        if (Math.abs(diff) > 0.1f) {
            // Ограничиваем максимальное изменение за один кадр
            float maxChange = 3.0f; // максимальное изменение в градусах за кадр
            float change = Math.signum(diff) * Math.min(Math.abs(diff * SMOOTHING_FACTOR), maxChange);
            currentAzimuth += change;
            currentAzimuth = normalizeAngle(currentAzimuth);
            postInvalidateOnAnimation();
        }
        
        // Деления и метки по кругу
        for (int degree = 0; degree < 360; degree += 30) {
            float angle = (float) Math.toRadians(degree - currentAzimuth);
            float x1 = cx + (float) Math.sin(angle) * (radius * 0.85f);
            float y1 = cy - (float) Math.cos(angle) * (radius * 0.85f);
            float x2 = cx + (float) Math.sin(angle) * radius;
            float y2 = cy - (float) Math.cos(angle) * radius;
            paint.setStrokeWidth(2 * scaleFactor);
            canvas.drawLine(x1, y1, x2, y2, paint);
            
            if (degree % 90 == 0) {
                int directionIndex = (degree / 90) % 4;
                String[] mainDirections = {"N", "E", "S", "W"};
                float dx = cx + (float) Math.sin(angle) * (radius - 25 * scaleFactor);
                float dy = cy - (float) Math.cos(angle) * (radius - 25 * scaleFactor);
                paint.setTextSize(16 * scaleFactor);
                canvas.drawText(mainDirections[directionIndex], dx, dy, paint);
            }
        }
        
        // Рисуем суда по кругу
        for (AISVessel vessel : nearbyVessels) {
            float bearing = getShortestRotation(currentAzimuth, (float) vessel.getCourse());
            float angle = (float) Math.toRadians(bearing);
            float vesselRadius = radius * 0.6f;
            float vx = cx + (float) Math.sin(angle) * vesselRadius;
            float vy = cy - (float) Math.cos(angle) * vesselRadius;
            double distance = ourVessel != null ? GeoUtils.calculateDistance(ourVessel, vessel) : 0;
            float size = calculateVesselSize((float) distance) * scaleFactor;
            vesselPaint.setColor(getVesselColor(vessel));
            drawVesselTriangle(canvas, vx, vy, size, (float) (vessel.getCourse() - currentAzimuth));
        }
        
        // Центральная линия (направление вперёд)
        paint.setColor(Color.RED);
        paint.setStrokeWidth(3 * scaleFactor);
        canvas.drawLine(cx, cy, cx, cy - radius, paint);
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(1);
        
        // Текст азимута в центре
        paint.setTextSize(14 * scaleFactor);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText((int)currentAzimuth + "°", cx, cy + 5 * scaleFactor, paint);
        

    }

    private float calculateVesselSize(float distance) {
        if (distance > MAX_DISPLAY_DISTANCE) return MIN_VESSEL_SIZE;
        // Линейная интерполяция размера от расстояния
        float ratio = 1 - Math.min(distance / MAX_DISPLAY_DISTANCE, 1);
        return MIN_VESSEL_SIZE + (MAX_VESSEL_SIZE - MIN_VESSEL_SIZE) * ratio;
    }

    private int getVesselColor(AISVessel vessel) {
        // Можно настроить цвета в зависимости от параметров судна
        // Используем navigation status из AIS данных
        int navStatus = GeoUtils.getNavigationStatusCode(vessel.getNavigationalStatus());
        switch (navStatus) {
            case 0: // Under way using engine
                return Color.GREEN;
            case 1: // At anchor
                return Color.YELLOW;
            case 5: // Moored
                return Color.BLUE;
            default:
                return Color.WHITE;
        }
    }

    private void drawVesselTriangle(Canvas canvas, float x, float y, float size, float rotation) {
        vesselPath.reset();
        
        // Создаем треугольник
        float halfSize = size / 2;
        vesselPath.moveTo(x, y - halfSize); // вершина
        vesselPath.lineTo(x - halfSize, y + halfSize); // левый нижний угол
        vesselPath.lineTo(x + halfSize, y + halfSize); // правый нижний угол
        vesselPath.close();

        // Поворачиваем треугольник
        canvas.save();
        canvas.rotate(rotation, x, y);
        canvas.drawPath(vesselPath, vesselPaint);
        canvas.restore();
    }

    public void setAzimuth(float azimuth) {
        // Проверяем на валидность азимута
        if (Float.isNaN(azimuth) || Float.isInfinite(azimuth)) {
            return; // Игнорируем невалидные значения
        }
        
        // Нормализуем входящий азимут
        this.targetAzimuth = normalizeAngle(azimuth);
        
        // Если текущий азимут еще не инициализирован, устанавливаем его сразу
        if (currentAzimuth == 0 && targetAzimuth != 0) {
            currentAzimuth = targetAzimuth;
        }
        
        // Специальная обработка для 0° - если текущий азимут близок к 360°, 
        // то 0° должен интерпретироваться как 360°
        if (targetAzimuth == 0 && currentAzimuth > 350) {
            this.targetAzimuth = 360;
        }
        
        invalidate();
    }
    
    public void setMagneticCompass(float magneticCompass) {
        this.magneticCompass = magneticCompass;
        invalidate();
    }

    public void updateNearbyVessels(List<AISVessel> vessels) {
        this.nearbyVessels = vessels;
        invalidate();
    }
    
    public void setOurVessel(Vessel ourVessel) {
        this.ourVessel = ourVessel;
        invalidate();
    }
}
