using System;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Army Drawer", menuName = "Army Drawer")]
public sealed class ArmyDrawer : ScriptableObject
{
    [SerializeField]
    private UnitDrawParams[] drawParams = null;
    [SerializeField]
    public Vector3 scale = Vector3.one;
    [SerializeField]
    private int defaultCount = 100;

    private List<List<Matrix4x4>> drawPositions = null;

    [Serializable]
    public sealed class UnitDrawParams {
        [SerializeField]
        public Mesh Mesh = null;
        [SerializeField]
        public Material[] Materials = null;
    }

    public void DrawWithMain(Vector3 position, float angle, List<Vehicle> units, Vehicle mainVehicle, int factionId)
    {
        if (drawPositions == null)
            drawPositions = CreateDrawPositions();

        ClearDrawPositions();

        var quaternion = Quaternion.Euler(0, angle, 0);

        for (int i = 0; i < units.Count; i++)
        {
            var unit = units[i];
            if (unit != null && unit.IsAlive) {
                drawPositions[unit.Blueprint.MeshId].Add(Matrix4x4.TRS(position + unit.Offset, quaternion, scale));
            }
        }
        drawPositions[mainVehicle.Blueprint.MeshId].Add(Matrix4x4.TRS(position + mainVehicle.Offset, quaternion, scale));
        for (int i = 0; i < drawParams.Length; i++) {
            var positions = drawPositions[i];
            if (positions.Count > 0)
                Graphics.DrawMeshInstanced(drawParams[i].Mesh, 0, drawParams[i].Materials[factionId], positions);
        }
    }

    public void Draw(Vector3 position, float angle, List<Vehicle> units, int factionId)
    {
        if (drawPositions == null)
            drawPositions = CreateDrawPositions();

        ClearDrawPositions();

        var quaternion = Quaternion.Euler(0, angle, 0);

        for (int i = 0; i < units.Count; i++)
        {
            var unit = units[i];
            if (unit != null && unit.IsAlive)
            {
                drawPositions[unit.Blueprint.MeshId].Add(Matrix4x4.TRS(position + unit.Offset, quaternion, scale));
            }
        }
        for (int i = 0; i < drawParams.Length; i++)
        {
            var positions = drawPositions[i];
            if (positions.Count > 0)
                Graphics.DrawMeshInstanced(drawParams[i].Mesh, 0, drawParams[i].Materials[factionId], positions);
        }
    }

    private void ClearDrawPositions() => drawPositions.ForEach(positions => positions.Clear());

    private List<List<Matrix4x4>> CreateDrawPositions()
    {
        var drawPositions = new List<List<Matrix4x4>>(drawParams.Length);
        for (int i = 0; i < drawParams.Length; i++)
        {
            drawPositions.Add(new List<Matrix4x4>(defaultCount));
        }
        return drawPositions;
    }
}
