using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;

public enum MeasureMode
{
    None,
    Line,
    Rectangle,
    Polygon,
    Circle
}

public class MeasureManager : MonoBehaviour
{
    private Camera cam;

    [SerializeField] private GameObject distanceLabelPrefab;
    [SerializeField] private GameObject deleteButtonPrefab;
    [SerializeField] private GameObject lineInfoPrefab;
    [SerializeField] private GameObject polygonInfoPrefab;
    [SerializeField] private GameObject circleInfoPrefab;   

    [SerializeField] private RectTransform labelRoot;
    [SerializeField] private RectTransform infoPopupRoot;
    [SerializeField] private Transform measureGroupRoot;

    [SerializeField] private Material lineMaterial;

    private MeasureGroup currentGroup;
    private List<MeasureGroup> groups = new List<MeasureGroup>();

    private float scaleMultiplier = 0.1f;
    private float lineWidth = 0.02f;
    public bool isMeasuring = false;

    public MeasureMode currentMeasureMode = MeasureMode.None;

    private void Awake()
    {
        cam = Camera.main;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0) && TryGetClickPosition(out Vector3 hitPos))
        {
            if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject())
                return;

            if (!isMeasuring)
            {
                CreateMeasureGroup();
            }
            currentGroup.AddPoint(hitPos);
        }

        if (Input.GetMouseButtonDown(1)) 
        {
            if (isMeasuring)
            {
                currentGroup.EndMeasure();
                isMeasuring = false;
            }
        }

        if (Input.GetKeyDown(KeyCode.Escape)) // Test
        {
            ResetAll();
        }

        if (isMeasuring && currentGroup != null)
        {
            if (TryGetClickPosition(out Vector3 mousePos))
            {
                currentGroup.UpdatePreviewLine(mousePos);
                if (currentGroup is LineMeasureGroup lineGroup)
                {
                    lineGroup.UpdateInfoPopupPos(mousePos);
                }
            }
        }
    }

    private void CreateMeasureGroup()
    {
        MeasureGroup group = null;
        Color color = Color.white;

        switch (currentMeasureMode)
        {
            case MeasureMode.Line:
                group = new GameObject("LineMeasureGroup").AddComponent<LineMeasureGroup>();
                color = Color.white;    
                break;
            case MeasureMode.Rectangle:
                group = new GameObject("RectangleMeasureGroup").AddComponent<RectangleMeasureGroup>();
                color = Color.red;
                break;
            case MeasureMode.Polygon:
                group = new GameObject("PolygonMeasureGroup").AddComponent<PolygonMeasureGroup>();
                color = Color.yellow;
                break;
            case MeasureMode.Circle:
                group = new GameObject("CircleMeasureGroup").AddComponent<CircleMeasureGroup>();
                color = Color.green;
                break;
            case MeasureMode.None:
                return;
        }

        LineRenderer line = group.gameObject.AddComponent<LineRenderer>();
        line.material = lineMaterial;
        line.widthMultiplier = lineWidth;
        line.positionCount = 0;
        line.useWorldSpace = true;
        line.startColor = color;    
        line.endColor = color;  

        group.Init(
            line,
            distanceLabelPrefab,
            deleteButtonPrefab,
            lineInfoPrefab,
            polygonInfoPrefab,
            circleInfoPrefab,
            labelRoot,
            infoPopupRoot,
            scaleMultiplier,
            lineWidth,
            lineMaterial);

        currentGroup = group;
        groups.Add(group);
        group.transform.SetParent(measureGroupRoot);
        isMeasuring = true;
    }

    private void ResetAll()
    {
        foreach (LineMeasureGroup g in groups)
        {
            g.DestroyAll();
        }
           
        groups.Clear();
        isMeasuring = false;
    }

    private bool TryGetClickPosition(out Vector3 hitPos)
    {
        hitPos = Vector3.zero;
        Ray ray = cam.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit))
        {
            hitPos = hit.point;
            return true;
        }
        return false;
    }
}
