﻿using System;
using System.IO;
using System.Xml;
using Oni.Metadata;

namespace Oni.Xml
{
    internal class FilmToXmlConverter : RawXmlExporter
    {
        public FilmToXmlConverter(BinaryReader reader, XmlWriter writer)
            : base(reader, writer)
        {
        }

        private static readonly MetaType filmHeader = new MetaStruct("FilmHeader",
            new Field(MetaType.Vector3, "Position"),
            new Field(MetaType.Float, "Facing"),
            new Field(MetaType.Float, "DesiredFacing"),
            new Field(MetaType.Float, "HeadFacing"),
            new Field(MetaType.Float, "HeadPitch"),
            new Field(MetaType.Int32, "FrameCount"),
            new Field(MetaType.Padding(28)));

        private static readonly MetaType filmAnimations = new MetaStruct("FilmAnimations",
            new Field(MetaType.Array(2, MetaType.String128), "Animations"));

        private static readonly MetaType filmFrames = new MetaStruct("FilmFrames",
            new Field(MetaType.VarArray(new MetaStruct("Frame",
                new Field(MetaType.Vector2, "MouseDelta"),
                new Field(MetaType.Enum<InstanceMetadata.FILMKeys>(), "Keys"),
                new Field(MetaType.Int32, "Frame"),
                new Field(MetaType.Padding(4))
            )), "Frames")
        );

        public static void Convert(string filePath, string outputDirPath)
        {
            using (var reader = new BinaryReader(filePath, true))
            using (var writer = CreateXmlWriter(Path.Combine(outputDirPath, Path.GetFileNameWithoutExtension(filePath) + ".xml")))
            {
                writer.WriteStartElement("Instance");
                writer.WriteAttributeString("id", "0");
                writer.WriteAttributeString("type", "FILM");

                var converter = new FilmToXmlConverter(reader, writer);

                reader.Position = filmAnimations.Size;
                filmHeader.Accept(converter);

                reader.Position = 0;
                filmAnimations.Accept(converter);

                reader.Position = filmAnimations.Size + filmHeader.Size;
                filmFrames.Accept(converter);

                writer.WriteEndElement();
            }
        }

        private static XmlWriter CreateXmlWriter(string filePath)
        {
            var settings = new XmlWriterSettings
            {
                CloseOutput = true,
                Indent = true,
                IndentChars = "    "
            };

            var stream = File.Create(filePath);
            var writer = XmlWriter.Create(stream, settings);

            try
            {
                writer.WriteStartElement("Oni");
            }
            catch
            {
#if NETCORE
                writer.Dispose();
#else
                writer.Close();
#endif
                throw;
            }

            return writer;
        }
    }
}
