using System;
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
public sealed class FireRangeView : MonoBehaviour
{
    [SerializeField]
    private float minRadius = 1;
    [SerializeField]
    private float maxRadius = 2;
    [SerializeField]
    private float pointsPerUnit = 10;
    [SerializeField]
    private Vector3 offset = Vector3.zero;
    [SerializeField]
    private MeshFilter meshFilter = null;

    [ContextMenu("Regenerate Mesh")]
    private void Start()
    {
        meshFilter.mesh = RegenerateMesh(minRadius, maxRadius, pointsPerUnit);
    }

    public void SetRange(float minRange, float maxRange)
    {
        minRadius = minRange;
        maxRadius = maxRange;
        meshFilter.mesh = RegenerateMesh(minRadius, maxRadius, pointsPerUnit);
    }

    private Mesh RegenerateMesh(float minRange, float maxRange, float pointsPerUnit)
    {
        var maxPerimeter = maxRange * 2f * Mathf.PI;
        var details = Mathf.Max(6, Mathf.CeilToInt(maxPerimeter * pointsPerUnit));
        var angleOffsets = new Vector3[details];
        for (int i = 0; i < details; i++) {
            var angleRadian = 2f * Mathf.PI * i / details;
            angleOffsets[i] = new Vector3(Mathf.Cos(angleRadian), 0, Mathf.Sin(angleRadian)) + offset;
        }
        var generator = new MeshGenerator("fire_range");
        for (int i = 0; i < details; i++) {
            var currAngle = angleOffsets[i];
            var nextAngle = angleOffsets[(i + 1) % angleOffsets.Length];
            var tlPoint = currAngle * maxRange;
            var trPoint = nextAngle * maxRange;
            var brPoint = nextAngle * minRange;
            var blPoint = currAngle * minRange;
            generator.AddTexturedQuad(
                 trPoint, tlPoint, blPoint, brPoint,
                Vector3.up, Vector3.up, Vector3.up, Vector3.up,
                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(1, 0),
                new Vector2(0, 0)
                );
        }
        return generator.Generate();
    }

    private void Reset()
    {
        meshFilter = GetComponent<MeshFilter>();
    }

    public void Show(bool needShow = true)
    {
        gameObject.SetActive(needShow);
    }

    public void Hide() => Show(false);

    internal void SetRange(object radius, object p)
    {
        throw new NotImplementedException();
    }
}
