using System.Collections.Generic;
using UnityEngine;

namespace pdinklag.CPW.Common
{
    public static class CAWMeshOcclusionUtility
    {
        private static readonly float VOXEL_SCALE = 1000000.0f;

        private static Vector3Int Voxelize(Vector3 v)
        {
            v *= VOXEL_SCALE;
            return new((int)v.x, (int)v.y, (int)v.z);
        }

        public static IReadOnlyCollection<Vector3Int> SelectionToVoxels(ItemSelection selection, Vector3[] vertices)
        {
            var n = vertices.Length;
            if (selection.Size != n)
            {
                Debug.LogErrorFormat("selection size ({0}) does not match number of vertices ({1})", selection.Size, n);
                return null;
            }

            var voxels = new HashSet<Vector3Int>(n);
            for (var i = 0; i < n; i++)
            {
                if (selection[i])
                {
                    voxels.Add(Voxelize(vertices[i]));
                }
            }

            return voxels;
        }

        public class VoxelToSelectionConverter
        {
            private readonly int _numVertices;
            private readonly Dictionary<Vector3Int, List<int>> _voxelMap;

            public int VertexCount => _numVertices;

            public VoxelToSelectionConverter(Vector3[] vertices)
            {
                _numVertices = vertices.Length;
                _voxelMap = new(_numVertices);
                for (var i = 0; i < _numVertices; i++)
                {
                    var v = Voxelize(vertices[i]);
                    if (!_voxelMap.TryGetValue(v, out var list))
                    {
                        list = new(1);
                        _voxelMap.Add(v, list);
                    }
                    list.Add(i);
                }
            }

            public ItemSelection VoxelsToSelection(IEnumerable<Vector3Int> voxels)
            {
                var sel = new ItemSelection();
                sel.SetSize(_numVertices);
                foreach (var v in voxels)
                {
                    if (_voxelMap.TryGetValue(v, out var vertexIndices))
                    {
                        foreach (var i in vertexIndices) sel[i] = true;
                    }
                }
                return sel;
            }
        }
    }
}
