using System;
using System.Threading.Tasks;
using Configurator;
using Discord;
using Discord.WebSocket;

namespace LapperThreads
{
    public class DiscordBot
    {
        //Get Lapper info and DiscordToken
        private GLDebug.Debug myDebug;
        private lexConfigurator newCfg;
        private string discordtoken = "";
        private string ReceiveMessageFromChannel = "";
        public static int ConnectedToDiscord = 0;
        public DiscordBot(lexConfigurator pnewCfg, GLDebug.Debug pmyDebug, string pdiscordtoken, string pdiscordchannel)
        {
            this.newCfg = pnewCfg;
            this.myDebug = pmyDebug;
            this.discordtoken = pdiscordtoken;
            this.ReceiveMessageFromChannel = pdiscordchannel;
        }

        public static DiscordSocketClient _client;
        public void TDiscordBot()
        {
            new DiscordBot(newCfg, myDebug, newCfg.varsLapper.DiscordToken, newCfg.varsLapper.DiscordChannelReceive).StartDiscordBot().GetAwaiter().GetResult();
        }

        public async Task StartDiscordBot()
        {
            if (!string.IsNullOrWhiteSpace(discordtoken))
            {
                myDebug.WriteLine("mss", "DiscordBot Thread Started...");

                if (string.IsNullOrWhiteSpace(ReceiveMessageFromChannel))
                {
                    myDebug.WriteLine("mss", "Warning: $DiscordChannelReceive is empty");
                }
               
                try
                {
                    //get operationsystem info
                    var os = Environment.OSVersion;
                    //Windows 10 
                    if ((os.Version.Major == 6)&&(os.Version.Minor == 2))
                    {
                        _client = new DiscordSocketClient();
                    }
                    //Windows 7 / 8 / 8.1
                    if ((os.Version.Major == 6)&&(os.Version.Minor == 1))
                    {
                        _client = new DiscordSocketClient(new DiscordSocketConfig { WebSocketProvider = Discord.Net.Providers.WS4Net.WS4NetProvider.Instance });
                    }
                    
                    //Login and start Discord client
                    await _client.LoginAsync(TokenType.Bot, discordtoken);
                    await _client.StartAsync();

                    //Events
                    //_client.MessageUpdated += MessageUpdated;
                    _client.MessageReceived += MessageReceived;

                    //When LFSLapper succeed to connect to the DiscordBot
                    _client.Ready += () =>
                    {
                        ;
                        myDebug.WriteLine("mss", "DiscordBot Connected");
                        Console.WriteLine("DiscordBot Connected");

                        ConnectedToDiscord = 1;

                        ChangeBotStatus(newCfg.varsLapper.DiscordBotStatus);
                        return Task.CompletedTask;
                    };
                    await Task.Delay(-1);
                }
                catch
                {
                    myDebug.WriteLine("err", "DiscordBot Connection failed. unauthorized");
                    Console.WriteLine("DiscordBot Connection failed. unauthorized");
                }
            }
        }

        public static void StopDiscordBot()
        {
            if (ConnectedToDiscord == 1)
            {
                _client.StopAsync();
            }
        }
        /*
        private async Task MessageUpdated(Cacheable<IMessage, ulong> before, SocketMessage after, ISocketMessageChannel channel)
        {
            // If the message was not in the cache, downloading it will result in getting a copy of `after`.
            var message = await before.GetOrDownloadAsync();
            Console.WriteLine($"{message} -> {after}");
        }
        */
        //Set discordbot status
        public static void ChangeBotStatus(string status)
        {
            _client.SetGameAsync(status);
        }

        //Receive Messages from the discordchannel
        public async Task MessageReceived(SocketMessage messageParam)
        {
            //Local Vars

            var message = messageParam as SocketUserMessage;
            var UserName = messageParam.Author.Username;
            var UserID = messageParam.Author.Id;
            var ChannelID = messageParam.Channel.Id;
            var ChannelName = messageParam.Channel.Name;
            var ChannelVerified = 0;

            string[] SplitDiscordReceiveChannel;
            //Stop from here when messages is sended by a bot
            if ((!message.Author.IsBot) && (UserName != ""))
            {
                //Convert vars to usable datatypes
                string msstring = message.Content.ToString();

                // Split Receive Channels
                if (ReceiveMessageFromChannel.IndexOf(",") != -1)
                    SplitDiscordReceiveChannel = ReceiveMessageFromChannel.Split(new string[] { "," }, StringSplitOptions.None);
                else
                    SplitDiscordReceiveChannel = new string[] { ReceiveMessageFromChannel };

                    if (SplitDiscordReceiveChannel.Length < 6)
                    {
                        //Verify Discord channel with the set receivingchannels in inc.lpr
                        for (int Channels = 0; Channels < SplitDiscordReceiveChannel.Length; Channels++)
                        {
                            if (ChannelID == UInt64.Parse(SplitDiscordReceiveChannel[Channels]))
                            {
                                string[] args = new string[5];
                                args[0] = ChannelID.ToString();
                                args[1] = ChannelName.ToString();
                                args[2] = UserID.ToString();
                                args[3] = UserName.ToString();
                                args[4] = msstring.ToString();
                                newCfg.executeFunction("OnReceiveDiscordMessage", null, args);

                                ChannelVerified = 1;
                            }
                        }
                    }  
                else
                {
                    throw new GLScript.GLApp.GLScriptException("Warning from OnReceiveDiscordMessage: Exceed the maximum channels. Maximum is 5");
                }

                if (ChannelVerified == 0)
                {
                    throw new GLScript.GLApp.GLScriptException("Warning from OnReceiveDiscordMessage: Channels could not be verified. Please set correct channels.");
                }
            }
        }

        //Send Messages to Discordchannel
        public static void SendDiscordBotMessage(ulong Senddiscordchannel, string SendMessage)
        {
            try
            {
                var chnl = _client.GetChannel(Senddiscordchannel) as IMessageChannel;
                chnl.SendMessageAsync(SendMessage);
            }
            catch
            {
                throw new GLScript.GLApp.GLScriptException("Error on Discordmessage: unable to send messages to discord.");
            }
        }
        public static void SendDiscordBotEmbed(ulong EmbedDiscordChannel, string EmbedTitle, string EmbedDescription, uint EmbedColor, string EmbedFieldTitle, string EmbedFieldValue, string EmbedFieldInline, string EmbedFieldFooter, string ThumbNailURL, string ImageUrl)
        {
            //var chnl = _client.GetChannel(EmbedDiscordChannel) as IMessageChannel;
            //Console.WriteLine("Channel: " + EmbedDiscordChannel);
            string[] SplitFieldTitle;
            string[] SplitFieldValue;
            string[] SplitFieldInLine;

            string[] SplitFooter;
            string FooterText = "";
            string FooterImageURL = "";

            try
            {

                ///
                //When field contains multiple fields
                ///
                if (EmbedFieldTitle.IndexOf("%nf%") != -1)
                {
                    SplitFieldTitle = EmbedFieldTitle.Split(new string[] { "%nf%" }, StringSplitOptions.None);
                    SplitFieldValue = EmbedFieldValue.Split(new string[] { "%nf%" }, StringSplitOptions.None);
                    SplitFieldInLine = EmbedFieldInline.Split(new string[] { "%nf%" }, StringSplitOptions.None);

                    //Warning message when Field are not equal
                    if ((SplitFieldTitle.Length != SplitFieldValue.Length) || (SplitFieldValue.Length != SplitFieldInLine.Length))
                    {
                        throw new GLScript.GLApp.GLScriptException("Error on SendDiscordEmbed(); Number of fields are not equal. Be sure number of FieldTitle & FieldValue & FieldInLine are the same");
                    }
                }
                else
                {
                    SplitFieldTitle = new string[] { EmbedFieldTitle };
                    SplitFieldValue = new string[] { EmbedFieldValue };
                    SplitFieldInLine = new string[] { EmbedFieldInline };
                }

                ///
                //Footer stringsplit.
                ///
                if (EmbedFieldFooter.IndexOf("%nf%") != -1)
                {
                    SplitFooter = EmbedFieldFooter.Split(new string[] { "%nf%" }, StringSplitOptions.None);
                    FooterText = SplitFooter[0];
                    FooterImageURL = SplitFooter[1];
                }
                else
                {
                    SplitFooter = new string[] { EmbedFieldFooter };
                    FooterText = SplitFooter[0];
                }
                //Build Embed.

                var embed = new EmbedBuilder();
                embed.WithColor(EmbedColor);
                // Console.WriteLine("Color: " + EmbedColor);

                if (EmbedTitle != "")
                    embed.WithTitle(EmbedTitle);
                if (EmbedDescription != "")
                    embed.WithDescription(EmbedDescription);
                if (ThumbNailURL != "")
                    embed.WithThumbnailUrl(ThumbNailURL);
                if (ImageUrl != "")
                    embed.WithImageUrl(ImageUrl);

                //Console.WriteLine("Title: " + EmbedTitle);
                //Console.WriteLine("EmbedDescription: " + EmbedDescription);
                //Console.WriteLine("ThumbNailURL: " + ThumbNailURL);
                //Console.WriteLine("ImageUrl: " + ImageUrl);

                if (FooterText != "")
                {
                    if (SplitFooter.Length > 1)
                        embed.WithFooter(FooterText, FooterImageURL);
                    else
                        embed.WithFooter(FooterText);
                }
                //Console.WriteLine("FooterText: " + FooterText);

                //Create a new field for each %nf%
                for (int i = 0; i < SplitFieldTitle.Length; i++)
                {
                    Boolean ConvertedFieldInLine = false;
                    ConvertedFieldInLine = Boolean.Parse(SplitFieldInLine[i]);

                    if (SplitFieldTitle[i] == "")
                        SplitFieldValue[i] = " ";

                    if (SplitFieldValue[i] == "")
                        SplitFieldValue[i] = " ";

                    embed.AddField(SplitFieldTitle[i], SplitFieldValue[i], ConvertedFieldInLine);
                    //Console.WriteLine("Field: " + SplitFieldTitle[i] + " || " + SplitFieldValue[i] + " || " + ConvertedFieldInLine);
                }
                if (ConnectedToDiscord == 1)
                {
                    var chnl = _client.GetChannel(EmbedDiscordChannel) as IMessageChannel;
                    chnl.SendMessageAsync("", false, embed.Build(), null);
                }
                else
                {
                    throw new GLScript.GLApp.GLScriptException("Warning on SendDiscordEmbed(); Unable to send Discord Embed, LFSLapper is not connected to Discord.");
                }
            }
            catch
            {
                throw new GLScript.GLApp.GLScriptException("Warning on SendDiscordEmbed(); Unable to send Discord Embed, Something went wrong.");
            }
        }
    }
}