using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using UnityEngine;

namespace MuzikaGromche
{
#if DEBUG
    // Dumps list of tracks as a JSON on launch. 
    static class Exporter
    {
        public static void ExportTracksJSON(ISelectableTrack[] tracks)
        {
            // Same directory where save files are located:
            // C:\Users\user\AppData\LocalLow\ZeekerssRBLX\Lethal Company\
            string directory = Application.persistentDataPath;
            string fileName = "MuzikaGromcheTracks.json";
            string filePath = Path.Join(directory, fileName);

            var jsonObject = new Dictionary<string, object>();
            var tracksList = new List<object>();
            jsonObject["version"] = MyPluginInfo.PLUGIN_VERSION;
            jsonObject["tracks"] = tracksList;
            foreach (var (selectableTrack, audioTrack) in SelectTracks(tracks))
            {
                tracksList.Add(SerializeTrack(selectableTrack, audioTrack));
            }

            using StreamWriter sw = new(filePath);
            using JsonWriter writer = new JsonTextWriter(sw)
            {
                Formatting = Formatting.Indented,
            };
            JsonSerializer serializer = new()
            {
                NullValueHandling = NullValueHandling.Include,
            };
            serializer.Serialize(writer, jsonObject);
        }

        private static IEnumerable<(ISelectableTrack selectableTrack, IAudioTrack audioTrack)> SelectTracks(ISelectableTrack[] tracks)
        {
            foreach (var selectableTrack in tracks)
            {
                foreach (var audioTrack in selectableTrack.GetTracks())
                {
                    yield return (selectableTrack, audioTrack);
                }
            }
        }

        private static Dictionary<string, object?> SerializeTrack(ISelectableTrack selectableTrack, IAudioTrack audioTrack)
        {
            var obj = new Dictionary<string, object?>
            {
                ["Enabled"] = selectableTrack.Enabled,
                ["Name"] = audioTrack.Name, // may be different from selectableTrack.Name, if selectable track is a group
                ["Artist"] = selectableTrack.Artist,
                ["Song"] = selectableTrack.Song,
                ["IsExplicit"] = selectableTrack.IsExplicit,
                ["Season"] = selectableTrack.Season?.Name,
                ["Language"] = selectableTrack.Language.Full,
                ["WindUpTimer"] = audioTrack.WindUpTimer,
                ["Bpm"] = audioTrack.Bpm,
                ["Beats"] = audioTrack.Beats,
                ["LoopOffset"] = audioTrack.LoopOffset,
                ["Ext"] = audioTrack.Ext,
                ["FileDurationIntro"] = audioTrack.LoadedIntro?.length ?? 0f,
                ["FileDurationLoop"] = audioTrack.LoadedLoop?.length ?? 0f,
                ["FileNameIntro"] = audioTrack.FileNameIntro,
                ["FileNameLoop"] = audioTrack.FileNameLoop,
                ["BeatsOffset"] = audioTrack.BeatsOffset,
                ["FadeOutBeat"] = audioTrack.FadeOutBeat,
                ["FadeOutDuration"] = audioTrack.FadeOutDuration,
                ["ColorTransitionIn"] = audioTrack.ColorTransitionIn,
                ["ColorTransitionOut"] = audioTrack.ColorTransitionOut,
                ["ColorTransitionEasing"] = audioTrack.ColorTransitionEasing.Name,
                ["FlickerLightsTimeSeries"] = audioTrack.FlickerLightsTimeSeries,
                ["Lyrics"] = SerializeTimeSeries(new TimeSeries<string>(audioTrack.LyricsTimeSeries, audioTrack.LyricsLines)),
                ["DrunknessLoopOffsetTimeSeries"] = SerializeTimeSeries(audioTrack.DrunknessLoopOffsetTimeSeries),
                ["CondensationLoopOffsetTimeSeries"] = SerializeTimeSeries(audioTrack.CondensationLoopOffsetTimeSeries),
                ["Palette"] = audioTrack.Palette.Colors.Select(SerializeColor).ToList(),
                ["GameOverText"] = audioTrack.GameOverText,
            };
            return obj;
        }

        private static object SerializeTimeSeries<T>(TimeSeries<T> timeSeries)
        {
            return timeSeries.Beats.Zip(timeSeries.Values, (one, two) => new object?[] { one, two }).ToList();
        }

        private static string SerializeColor(Color color)
        {
            string colorHex = $"#{ColorUtility.ToHtmlStringRGB(color)}";
            return colorHex;
        }
    }
#endif
}
