using BarRaider.SdTools;
using BarRaider.SdTools.Wrappers;
using ClipTrimDotNet.Client;
using NAudio.CoreAudioApi.Interfaces;
using NAudio.Wave;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClipTrimDotNet
{
    public class DataSourceItem
    {
        public string label { get; set; }
        public string value { get; set; }
    }
    [PluginActionId("com.michal-courson.cliptrim.profile-switcher")]
    public class ProfileSwitcher : KeypadBase
    {
        private class PluginSettings
        {
            public static PluginSettings CreateDefaultSettings()
            {
                PluginSettings instance = new PluginSettings();
                instance.ProfileName = null;
                return instance;
            }

            [JsonProperty(PropertyName = "profileName")]
            public string? ProfileName { get; set; }
        }

        #region Private Members

        private PluginSettings settings;

        #endregion
        public ProfileSwitcher(SDConnection connection, InitialPayload payload) : base(connection, payload)
        {
            if (payload.Settings == null || payload.Settings.Count == 0)
            {
                this.settings = PluginSettings.CreateDefaultSettings();
                SaveSettings();
            }
            else
            {
                this.settings = payload.Settings.ToObject<PluginSettings>();
            }
            GlobalSettingsManager.Instance.RequestGlobalSettings();
            Connection.OnSendToPlugin += Connection_OnSendToPlugin;
            SetTitle();
        }

        private async void SetTitle()
        {

            await Connection.SetTitleAsync(settings.ProfileName + " A");
        }

        private async void Connection_OnSendToPlugin(object sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.SendToPlugin> e)
        {
            //Logger.Instance.LogMessage(TracingLevel.INFO, "get profiles");
            if (e.Event.Payload["event"].ToString() == "getProfiles")
            {
                //string basePath = "C:\\Users\\mickl\\Music\\clips";
                //var files = Directory.GetDirectories(basePath, "*", SearchOption.TopDirectoryOnly).Select(x => Path.GetFileNameWithoutExtension(x)).Where(x => x != "original");
                var files = ClipTrimClient.Instance.GetCollectionNames();
                var items = files.Select(x => new DataSourceItem { label = x, value = x});
                var obj = new JObject();
                obj["event"] = "getProfiles";
                obj["items"] = JArray.FromObject(items);
                //Logger.Instance.LogMessage(TracingLevel.INFO, "get profiles return " + JsonConvert.SerializeObject(obj));
                await Connection.SendToPropertyInspectorAsync(obj);
            }
            if (e.Event.Payload["event"].ToString() == "getOutputDevices")
            {
                List<WaveOutCapabilities> devices = new List<WaveOutCapabilities>();
                for (int n = -1; n < WaveOut.DeviceCount; n++)
                {
                    var caps = WaveOut.GetCapabilities(n);
                    devices.Add(caps);
                }
                var items = devices.Select(x => new DataSourceItem { label = x.ProductName, value = x.ProductName });
                var obj = new JObject();
                obj["event"] = "getOutputDevices";
                obj["items"] = JArray.FromObject(items);
                //Logger.Instance.LogMessage(TracingLevel.INFO, "get devices return " + JsonConvert.SerializeObject(obj));
                await Connection.SendToPropertyInspectorAsync(obj);
            }
            
        }

        private void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.TitleParametersDidChange> e)
        {
        }

        public override void Dispose()
        {
            Connection.OnTitleParametersDidChange -= Connection_OnTitleParametersDidChange;
            //Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called");
        }

        public override async void KeyPressed(KeyPayload payload)
        {
            //Logger.Instance.LogMessage(TracingLevel.INFO, "KeyPressed");
            //Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(settings));
            //Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(GlobalSettings.Instance));
            ClipTrimClient.Instance.SetSelectedCollectionByName(settings.ProfileName);
            GlobalSettings.Instance.SetCurrentProfile(settings.ProfileName);
            Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(GlobalSettings.Instance));

            await Connection.SetGlobalSettingsAsync(JObject.FromObject(GlobalSettings.Instance));
            await Connection.SwitchProfileAsync("ClipTrim");
        }

        public override void KeyReleased(KeyPayload payload)
        {

        }

        public override void OnTick()
        {
            SetTitle();
        }

        public override void ReceivedSettings(ReceivedSettingsPayload payload)
        {
            Tools.AutoPopulateSettings(settings, payload.Settings);
            SaveSettings();
            //tTitle();
            //CheckFile();
        }

        public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload)
        {
            //Logger.Instance.LogMessage(TracingLevel.INFO, "ReceivedGlobalSettings");

            if (payload.Settings == null || payload.Settings.Count == 0)
            {
                var inst = GlobalSettings.Instance;
                //GlobalSettingsManager.Instance.SetGlobalSettings(JObject.FromObject(inst));
            }
            else
            {
                GlobalSettings.Instance = payload.Settings.ToObject<GlobalSettings>();
            }

            //CheckFile();
        }

        #region Private Methods

        private Task SaveSettings()
        {
            return Connection.SetSettingsAsync(JObject.FromObject(settings));
        }

        #endregion
    }
}