using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;

namespace EduNetworkBuilder
{
    /// <summary>
    /// This tracks everything that happened to a packet in transit
    /// </summary>
    /// 
    [Serializable]
    public struct DebugMessage
    {
        public DebugLevel WhatLevel;
        public string HostName;
        public string Message;
        public DebugMessage(DebugLevel tLevel, string tHost, string tMessage)
        {
            WhatLevel = tLevel;
            HostName = tHost;
            Message = tMessage;
        }
    }

    [Serializable]
    public class PacketMessage
    {
        public List<DebugMessage> Messages = new List<DebugMessage>();
        public string _Status = ""; //Usually "success" or "failed"
        public bool Finished = false;
        public TimeSpan duration;
        public string Status
        {
             get { return _Status; }
             set { if (!Finished) _Status = value; }
        }

        public PacketMessage() { }
        public PacketMessage(string Host, string OneMessage)
        {
            DebugMessage DM = new DebugMessage(DebugLevel.info, Host, OneMessage);
            Status = OneMessage;
            Messages.Add(DM);
        }

        public static T Clone<T>(T source)
        {
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException(NB.Translate("NC_CloneSerialzable"), NB.Translate("_source"));
            }

            // Don't serialize a null object, simply return the default for that object
            if (Object.ReferenceEquals(source, null))
            {
                return default(T);
            }

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }



        public void AddMessage(DebugLevel tLevel, string tHost, string tMessage)
        {
            if(!Finished)
                Messages.Add(new DebugMessage(tLevel, tHost, tMessage));
        }

        public void AddMessage(DebugLevel tLevel, NetworkComponent tHost, string tMessage)
        {
            string host = NB.Translate("PM_UnknownHost");
            if (tHost != null)
                host = tHost.hostname;
            if(! Finished)
                Messages.Add(new DebugMessage(tLevel, host, tMessage));
        }

        public List<string> GetMessagesLike(DebugLevel tLevel)
        {
            List<string> answer = new List<string>();
            string tString;
            foreach( DebugMessage tmessage in Messages)
            {
                if((tmessage.WhatLevel | tLevel) == tLevel)
                {
                    tString = NB.LeftPad(tmessage.HostName) + " " + NB.LeftPad(tmessage.WhatLevel.ToString()) + " " + tmessage.Message;
                    answer.Add(tString);
                }
            }
            return answer;
        }

        public List<string> GetMessagesSummary()
        {
            List<string> answer = new List<string>();
            string tString;
            int time = duration.Seconds * 1000 + duration.Milliseconds;
            tString = NB.LeftPad(time.ToString() + "ms ", 10) + Status;
            answer.Add(tString);
            return answer;
        }


    }
}
