using MailKit;
using MimeKit;

namespace InABox.Mail
{
    public class IMAPMailSummary : ICoreMailSummary
    {
        private IMAPMailSummary()
        {
        }

        public IMAPMailSummary(IMailFolder folder, IMessageSummary summary)
        {
            Folder = folder;
            Summary = summary;
        }

        public IMailFolder Folder { get; }
        public IMessageSummary Summary { get; }

        public string ID => Summary.UniqueId.ToString();

        public DateTime Date => Summary.Envelope.Date.HasValue ? Summary.Envelope.Date.Value.LocalDateTime : DateTime.MinValue;

        public string From
        {
            get => Summary.Envelope.From.Any() ? ((MailboxAddress)Summary.Envelope.From.First()).Address : "";
            set
            {
                Summary.Envelope.From.Clear();
                Summary.Envelope.From.Add(MailboxAddress.Parse(value));
            }
        }

        public string Subject
        {
            get => Summary.Envelope.Subject;
            set => Summary.Envelope.Subject = value;
        }

        public IEnumerable<string> To
        {
            get { return Summary.Envelope.To.Select(x => ((MailboxAddress)x).Address); }
            set
            {
                Summary.Envelope.To.Clear();
                Summary.Envelope.To.AddRange(value.Select(x => MailboxAddress.Parse(x)));
            }
        }
    }

    public class IMAPMailMessage : ICoreMailMessage
    {
        private Tuple<string, byte[]>[] _attachments = { };

        private string _body = "";

        private bool _ishtml;

        private IMAPMailMessage()
        {
        }

        public IMAPMailMessage(IMailFolder folder, UniqueId uniqueid, MimeMessage message)
        {
            Folder = folder;
            UniqueID = uniqueid;
            Message = message;
            Summary = null;
            _body = message.HtmlBody;
        }

        public IMAPMailMessage(IMailFolder folder, UniqueId uniqueid, IMessageSummary summary)
        {
            Folder = folder;
            UniqueID = uniqueid;
            Message = null;
            Summary = summary;
        }

        public IMailFolder Folder { get; set; }
        public UniqueId UniqueID { get; private set; }
        public MimeMessage Message { get; }
        public IMessageSummary Summary { get; }

        public void Save()
        {
            if (UniqueID != UniqueId.MinValue)
                Folder.SetFlags(UniqueID, MessageFlags.Deleted, true);
            UniqueID = Folder.Append(Message).Value;
            Folder.SetFlags(UniqueID, MessageFlags.Seen, true);
        }

        public string ID
        {
            get => Message.MessageId;
            set => Message.MessageId = value;
        }

        public DateTime Date
        {
            get => Message.Date.DateTime;
            set => Message.Date = new DateTimeOffset(value);
        }

        public string From
        {
            get => (Message.From.First() as MailboxAddress).Address;
            set
            {
                Message.From.Clear();
                Message.From.Add(InternetAddress.Parse(value));
            }
        }

        public IEnumerable<string> To
        {
            get { return Message.To.Select(x => (x as MailboxAddress).Address); }
            set
            {
                Message.To.Clear();
                Message.To.AddRange(value.Select(x => InternetAddress.Parse(x)));
            }
        }

        public IEnumerable<string> CC
        {
            get { return Message.Cc.Select(x => (x as MailboxAddress).Address); }
            set
            {
                Message.Cc.Clear();
                Message.Cc.AddRange(value.Select(x => InternetAddress.Parse(x)));
            }
        }

        public IEnumerable<string> BCC
        {
            get { return Message.Bcc.Select(x => (x as MailboxAddress).Address); }
            set
            {
                Message.Bcc.Clear();
                Message.Bcc.AddRange(value.Select(x => InternetAddress.Parse(x)));
            }
        }

        public string Subject
        {
            get => Message.Subject;
            set => Message.Subject = value;
        }

        public IEnumerable<Tuple<string, byte[]>> Attachments
        {
            get => _attachments;
            set
            {
                _attachments = value.ToArray();
                UpdateMessage();
            }
        }

        public string Body
        {
            get => _body;
            set
            {
                _body = value;
                UpdateMessage();
            }
        }

        public bool IsHTML
        {
            get => _ishtml;
            set
            {
                _ishtml = value;
                UpdateMessage();
            }
        }

        public void Move(IMailFolder to)
        {
            if (UniqueID == UniqueId.MinValue)
                UniqueID = to.Append(Message).Value;
            else
                UniqueID = Folder.MoveTo(UniqueID, to).Value;
            Folder = to;
        }

        private void UpdateMessage()
        {
            var builder = new BodyBuilder();
            if (_ishtml)
                builder.HtmlBody = _body;
            else
                builder.TextBody = _body;
            if (_attachments != null)
                foreach (var attachment in _attachments)
                    builder.Attachments.Add(attachment.Item1, attachment.Item2);
            Message.Body = builder.ToMessageBody();
        }
    }
}