using System;
using System.Threading;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Configurator;
using Discord;
using Discord.Commands;
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 channel = messageParam.Channel.Id;
            //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();
                //If Set channel is equal to the channel where the command comes from.
                if (channel == UInt64.Parse(ReceiveMessageFromChannel))
                {
                    string[] args = new string[2];
                    args[0] = username.ToString();
                    args[1] = msstring.ToString();
                    newCfg.executeFunction("OnReceiveDiscordMessage", null, args);
                }
            }
        }

        //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.");
            }
        }
    }
}