using CesiumForUnity;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class LineMeasureGroup : MeasureGroup
{
    private LineMeasureGroupInfoPopup lineMeasureGroupInfoPopup;

    public override void AddPoint(Vector3 pos)
    {
        points.Add(pos);
        line.positionCount = points.Count;
        line.SetPosition(points.Count - 1, pos);

        GameObject label = Instantiate(labelPrefab, pos, Quaternion.identity, labelRoot);
        labels.Add(label);

        if (!lineMeasureGroupInfoPopup)
        {
            lineMeasureGroupInfoPopup = Instantiate(lineInfoPopupPrefab).GetComponent<LineMeasureGroupInfoPopup>();
            lineMeasureGroupInfoPopup.InitUI(infoPopupRoot);
        }

        if (points.Count >= 2)
        {
            Vector3 a = points[points.Count - 2];
            Vector3 b = points[points.Count - 1];

            double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, a);
            double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, b);

            double dist = GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);
            totalDistance += dist;
        }
    }

    public override void EndMeasure()
    {
        if (line == null)
            return;

        if (line.positionCount > points.Count)
            line.positionCount = points.Count;

        if (points.Count > 1)
        {
            Vector3 last = points[points.Count - 1];
            deleteButton = Instantiate(deleteButtonPrefab, last, Quaternion.identity, infoPopupRoot);
            deleteButton.GetComponentInChildren<Button>().onClick.AddListener(() => DestroyAll());
            deleteButton.transform.position = last + new Vector3(-20, 0, 20);
        }

        lineMeasureGroupInfoPopup.transform.position = points[points.Count - 1] + new Vector3(20, 0, 20);

        GameObject tempLabel = labels[labels.Count - 1];    
        labels.Remove(tempLabel);
        Destroy(tempLabel);
    }

    public override void DestroyAll()
    {
        base.DestroyAll();
        if (lineMeasureGroupInfoPopup)
            Destroy(lineMeasureGroupInfoPopup.gameObject);
        Destroy(this);
    }

    public override void LateUpdate()
    {
        base.LateUpdate();

        if (lineMeasureGroupInfoPopup)
        {
            lineMeasureGroupInfoPopup.transform.LookAt(lineMeasureGroupInfoPopup.transform.position + cam.transform.forward);
            float heightDiff = Mathf.Abs(cam.transform.position.y - lineMeasureGroupInfoPopup.transform.position.y);
            lineMeasureGroupInfoPopup.transform.localScale = Vector3.one * (heightDiff * lineScaleMultiplier);
        }
    }

    public override void UpdatePreviewLine(Vector3 mousePos)
    {
        if (line == null) return;

        if (points.Count == 1)
        {
            Vector3 point = points[0];
            line.positionCount = 2;
            line.SetPosition(0, point);
            line.SetPosition(1, mousePos);

            Vector3 mid = (point + mousePos) * 0.5f;
            labels[0].transform.position = mid;

            double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, point);
            double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, mousePos);
            double dist = GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);

            labels[0].GetComponentInChildren<TextMeshProUGUI>().text = $"{dist:F1} m";
            lineMeasureGroupInfoPopup?.UpdateInfo("(¾øÀ½)", llh_b.x, llh_b.y, dist);
        }
        else if (points.Count >= 2)
        {
            Vector3 last = points[points.Count - 1];
            line.positionCount = points.Count + 1;
            line.SetPosition(points.Count, mousePos);

            Vector3 mid = (last + mousePos) * 0.5f;
            labels[labels.Count - 1].transform.position = mid;

            double3 llh_a = GeoUtils.GetLonLatHeight(cesiumGeoreference, last);
            double3 llh_b = GeoUtils.GetLonLatHeight(cesiumGeoreference, mousePos);
            double dist = GeoUtils.Haversine(llh_a.x, llh_a.y, llh_b.x, llh_b.y);

            labels[labels.Count - 1].GetComponentInChildren<TextMeshProUGUI>().text = $"{dist:F1} m";

            double previewTotal = totalDistance + dist;
            lineMeasureGroupInfoPopup?.UpdateInfo("(¾øÀ½)", llh_b.x, llh_b.y, previewTotal);
        }
    }

    public void UpdateInfoPopupPos(Vector3 mousePos)
    {
        if (points.Count == 0 || line == null || lineMeasureGroupInfoPopup == null) return;
        lineMeasureGroupInfoPopup.transform.position = mousePos + new Vector3(20, 0, 20);
    }
}
