using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SFI.COMM.LIB.Redis
{
    public static class Commander
    {
        public static bool IsStarted { get; set; }
        public static string SenderKey { get; set; }
        public static Action<TransferCommand> CommandReceiver { get; set; }
        public static string Flag { get { return $"receiver-{Commander.SenderKey}"; } }


        public static void Start(string senderKey, Action<TransferCommand> commandReceiver)
        {
            Commander.SenderKey = senderKey;
            Commander.CommandReceiver = commandReceiver;

            Channel.Start(senderKey);

            Commander.IsStarted = true;
        }
        public static void Stop()
        {
            Channel.Stop();
        }
        public static string MakeFlag(string key)
        {
            return $"receiver-{key}";
        }




        
        public static List<ITransferAction> TransferActionList = new List<ITransferAction>();

        public static void Request(string receiverKey, CommandCollection command, object parameter = null)
        {
            Commander.Request(receiverKey, command, parameter, null);
        }
        public static void Request(string receiverKey, CommandCollection command, object parameter, string parameterName, string parameterValue)
        {
            Commander.Request(receiverKey, command, parameter, new List<CommandParameter>() { new CommandParameter() { Name = parameterName, Value = parameterValue } });
        }
        public static void Request(string receiverKey, CommandCollection command, object parameter, List<CommandParameter> parameters) 
        {
            Commander.Request<string>(receiverKey, command, parameter, parameters, null);
        }
        public static void Request<T>(string receiverKey, CommandCollection command, object parameter = null, Action<TransferResult<T>> resultAction = null)
        {
            Commander.Request<T>(receiverKey, command, parameter, null, resultAction);
        }
        public static void Request<T>(string receiverKey, CommandCollection command, object parameter, string parameterName, string parameterValue, Action<TransferResult<T>> resultAction = null)
        {
            Commander.Request<T>(receiverKey, command, parameter,  new List<CommandParameter>() { new CommandParameter() { Name = parameterName, Value = parameterValue } }, resultAction);
        }
        public static void Request<T>(string receiverKey, CommandCollection command, object parameter, List<CommandParameter> parameters, Action<TransferResult<T>> resultAction = null)
        {
            if (!Commander.IsStarted)
                throw new Exception("Real time hizmetleri başlatılmamış!");

            string commandKey = Guid.NewGuid().ToString();

            TransferCommand cmd = new TransferCommand();
            cmd.SenderKey = Commander.SenderKey;
            cmd.CommandKey = commandKey;
            cmd.ReceiverKey = receiverKey;
            cmd.Command = command;
            cmd.Parameters = parameters;
            cmd.Parameter = parameter;


            if (resultAction != null)
                Commander.TransferActionList.Add(new TransferAction<T>() { ResultAction = resultAction });


            TransferData data = new TransferData();
            data.Flag = Commander.MakeFlag(receiverKey);
            data.IsCommand = true;
            data.Command = cmd;

            Channel.SendData(JsonConvert.SerializeObject(data));

            cmd.Dispose();
            data.Dispose();
        }





        public static void Response(TransferCommand cmd, bool isSuccess = true, object data = null, string message = null, List<CommandParameter> parameters = null)
        {
            string receiverKey = cmd.SenderKey;

            TransferCommandResult cResult = new TransferCommandResult();
            cResult.CommandKey = cmd.CommandKey;
            cResult.SenderKey = Commander.SenderKey;
            cResult.ReceiverKey = receiverKey;

            TransferResult<String> resultData = new TransferResult<string>();
            resultData.Success = isSuccess;
            resultData.Message = message;
            resultData.Parameters = parameters;

            if (data != null)
            {
                resultData.Data = JsonConvert.SerializeObject(data);
                cResult.Data = JsonConvert.SerializeObject(resultData); ;
            }


            TransferData result = new TransferData();
            result.Flag = Commander.MakeFlag(receiverKey);
            result.IsCommand = false;
            result.Result = cResult;

            Channel.SendData(JsonConvert.SerializeObject(result));

            result.Dispose();
        }





        public static void Receiver(string data)
        {
            if (!data.Contains(Commander.Flag))
                return;

            TransferData result = JsonConvert.DeserializeObject<TransferData>(data);

            if (result.IsCommand)
            {
                if (Commander.CommandReceiver != null)
                    _ = Task.Run(() => ((Action<TransferCommand>)Commander.CommandReceiver.Clone())(result.Command));
            }
            else
            {
                TransferCommandResult cResult = result.Result;
                ITransferAction tAction = Commander.TransferActionList.FindAll(t => t.CommandKey == cResult.CommandKey).FirstOrDefault();

                if (tAction != null)
                    tAction.RunResult((string)cResult.Data.Clone());

                cResult.Dispose();
            }

            result.Dispose();
        }
    }


}
