using System;
using System.IO;
using System.Text;
using MeidoPhotoStudio.Converter.MultipleMaids;
using MeidoPhotoStudio.Converter.Utility;

namespace MeidoPhotoStudio.Converter.Converters
{
    public class MMPngConverter : IConverter
    {
        private static readonly byte[] KankyoHeader = Encoding.ASCII.GetBytes("KANKYO");
        private const string InputDirectoryName = "Input";
        public const string ConverterName = "ModifiedMM PNG";

        public void Convert(string workingDirectory)
        {
            var baseDirectory = Path.Combine(workingDirectory, ConverterName);
            var baseInputDirectory = Path.Combine(baseDirectory, InputDirectoryName);
            var baseOutputDirectory = Path.Combine(baseDirectory, MPSSceneSerializer.FormatDate(DateTime.Now));

            Convert(baseInputDirectory, baseOutputDirectory);
        }

        private static void Convert(string workingDirectory, string destination)
        {
            var directory = new DirectoryInfo(workingDirectory);

            if (!directory.Exists)
                return;

            Directory.CreateDirectory(destination);

            foreach (var file in directory.GetFiles("*.png"))
                ConvertScene(file.FullName, Path.Combine(destination, file.Name));

            foreach (var subDirectory in directory.GetDirectories())
            {
                var subDestination = Path.Combine(destination, subDirectory.Name);
                Convert(subDirectory.FullName, subDestination);
            }
        }

        private static void ConvertScene(string pngFile, string outputFilename)
        {
            var fileStream = File.OpenRead(pngFile);

            var thumbnailData = PngUtility.ExtractPng(fileStream) ?? MPSSceneSerializer.NoThumb;

            var kankyo = new byte[KankyoHeader.Length];
            fileStream.Read(kankyo, 0, KankyoHeader.Length);

            var background = false;

            // ModifiedMM habeebweeb fork scene data uses 'KANKYO' as a header to identify saved environments.
            // Regular scenes will lack a 'KANKYO' header so the filestream position has to be pulled back. 
            if (MeidoPhotoStudio.Plugin.Utility.BytesEqual(kankyo, KankyoHeader))
                background = true;
            else
                fileStream.Position -= KankyoHeader.Length;

            string sceneData;

            try
            {
                using var sceneStream = LZMA.Decompress(fileStream);
                sceneData = Encoding.Unicode.GetString(sceneStream.ToArray());
            }
            catch (Exception e)
            {
                if (Plugin.Instance == null)
                    return;

                Plugin.Instance.Logger.LogWarning($"Could not decompress scene data from {pngFile} because {e}");

                return;
            }

            if (string.IsNullOrEmpty(sceneData))
                return;

            byte[] convertedData;
            MeidoPhotoStudio.Plugin.SceneMetadata sceneMetadata;

            try
            {
                convertedData = MMSceneConverter.Convert(sceneData, background);
                sceneMetadata = MMSceneConverter.GetSceneMetadata(sceneData, background);
            }
            catch (Exception e)
            {
                if (Plugin.Instance == null)
                    return;

                Plugin.Instance.Logger.LogError($"Could not convert {pngFile} because {e}");
                return;
            }

            MPSSceneSerializer.SaveToFile(outputFilename, sceneMetadata, convertedData, thumbnailData);
        }
    }
}