﻿namespace Oni.Motoko
{
    internal class GeometryDatWriter
    {
        private Geometry geometry;
        private ImporterFile importer;

        public static ImporterDescriptor Write(Geometry geometry, ImporterFile importer)
        {
            var writer = new GeometryDatWriter
            {
                geometry = geometry,
                importer = importer
            };

            return writer.WriteGeometry();
        }

        private ImporterDescriptor WriteGeometry()
        {
            var triangleStrips = Stripify.FromTriangleList(geometry.Triangles);
            var triangleList = Stripify.ToTriangleList(triangleStrips);

            var faceNormals = new Vector3[triangleList.Length / 3];
            var faceIndices = new int[faceNormals.Length];

            for (int i = 0; i < triangleList.Length; i += 3)
            {
                var p0 = geometry.Points[triangleList[i + 0]];
                var p1 = geometry.Points[triangleList[i + 1]];
                var p2 = geometry.Points[triangleList[i + 2]];

                var faceNormal = Vector3.Normalize(Vector3.Cross(p1 - p0, p2 - p0));
                int faceIndex = i / 3;

                faceNormals[faceIndex] = faceNormal;
                faceIndices[faceIndex] = faceIndex;
            }

            var m3gm = importer.CreateInstance(TemplateTag.M3GM, geometry.Name);
            var pnta = importer.CreateInstance(TemplateTag.PNTA);
            var vcra1 = importer.CreateInstance(TemplateTag.VCRA);
            var vcra2 = importer.CreateInstance(TemplateTag.VCRA);
            var txca = importer.CreateInstance(TemplateTag.TXCA);
            var idxa1 = importer.CreateInstance(TemplateTag.IDXA);
            var idxa2 = importer.CreateInstance(TemplateTag.IDXA);

            using (var writer = m3gm.OpenWrite(4))
            {
                writer.Write(pnta);
                writer.Write(vcra1);
                writer.Write(vcra2);
                writer.Write(txca);
                writer.Write(idxa1);
                writer.Write(idxa2);

                if (geometry.TextureName != null)
                    writer.Write(importer.CreateInstance(TemplateTag.TXMP, geometry.TextureName));
                else
                    writer.Write(0);

                writer.Skip(4);
            }

            pnta.WritePoints(geometry.Points);
            vcra1.WriteVectors(geometry.Normals);
            vcra2.WriteVectors(faceNormals);
            txca.WriteTexCoords(geometry.TexCoords);
            idxa1.WriteIndices(triangleStrips);
            idxa2.WriteIndices(faceIndices);

            return m3gm;
        }
    }
}
