using System;
using System.Linq;
using System.Numerics;
using System.Xml.Serialization;
using LinqToTwitter;

namespace Azyobuzi.Twirunrun
{
    public class StatusInfo
        : IComparable<StatusInfo>, IEquatable<StatusInfo>
    {
        public StatusInfo() { }

        public StatusInfo(object obj)
        {
            if (obj is Status)
            {
                Tweet = (Status)obj;

                if (Tweet.Retweet == null)
                {
                    Type = StatusTypes.Tweet;
                    Id = Tweet.StatusID;
                    User = Tweet.User;
                    Text = Tweet.Text;
                    CreatedAt = Tweet.CreatedAt.ToLocalTime();
                    ReplyToStatusId = Tweet.InReplyToStatusID;
                    Favorited = Tweet.Favorited;
                    Source = new SourceClient(Tweet.Source);
                    IsProtected = Tweet.User.Protected;
                    ProfileImageUri = Tweet.User.ProfileImageUrl;
                }
                else
                {
                    Type = StatusTypes.Retweet;
                    Id = Tweet.StatusID;
                    User = Tweet.Retweet.RetweetingUser;
                    Text = Tweet.Retweet.Text;
                    CreatedAt = Tweet.Retweet.CreatedAt.ToLocalTime();
                    ReplyToStatusId = Tweet.Retweet.InReplyToStatusID;
                    Favorited = Tweet.Retweet.Favorited;
                    Source = new SourceClient(Tweet.Retweet.Source);
                    ProfileImageUri = Tweet.Retweet.RetweetingUser.ProfileImageUrl;
                }
            }
            else if (obj is AtomEntry)
            {
                TweetFromSearch = (AtomEntry)obj;
                Type = StatusTypes.Search;

                Id = TweetFromSearch.Alternate.Split('/')
                    .LastOrDefault(s =>
                    {
                        BigInteger dummy;
                        return BigInteger.TryParse(s, out dummy);
                    });
                var auther = TweetFromSearch.Author.Name.RegexMatch(@"^(?<screen_name>\w+)\s\((?<name>.+)\)$");
                User = new User
                {
                    Name = auther.Groups["name"].ToString(),
                    ScreenName = auther.Groups["screen_name"].ToString()
                };
                CreatedAt = TweetFromSearch.Published.ToLocalTime();
                Source = new SourceClient(TweetFromSearch.Source);
                ProfileImageUri = TweetFromSearch.Image;
            }
            else if (obj is DirectMessage)
            {
                DirectMessage = (DirectMessage)obj;
                Type = StatusTypes.DirectMessage;

                Id = DirectMessage.ID.ToString();
                User = DirectMessage.Sender;
                Text = DirectMessage.SenderScreenName.Equals(Settings.Instance.MyScreenName, StringComparison.InvariantCultureIgnoreCase) ?
                    string.Format("@{0} {1}", DirectMessage.RecipientScreenName, DirectMessage.Text) : DirectMessage.Text;
                CreatedAt = DirectMessage.CreatedAt.ToLocalTime();
                IsProtected = DirectMessage.Sender.Protected;
                ProfileImageUri = DirectMessage.Sender.ProfileImageUrl;
            }
            else
                throw new ArgumentException("対応していない値が渡されました。");
        }

        public Status Tweet { set; get; }
        public AtomEntry TweetFromSearch { set; get; }
        public DirectMessage DirectMessage { set; get; }
        public StatusTypes Type { set; get; }

        [XmlIgnore]
        public string Id { set; get; }
        [XmlIgnore]
        public User User { set; get; }
        [XmlIgnore]
        public string Text { set; get; }
        [XmlIgnore]
        public DateTime CreatedAt { set; get; }
        [XmlIgnore]
        public string ReplyToStatusId { set; get; }
        [XmlIgnore]
        public bool Favorited { get; set; }
        [XmlIgnore]
        public SourceClient Source { set; get; }
        //public Retweet Retweet { set; get; }
        [XmlIgnore]
        public bool IsProtected { set; get; }
        [XmlIgnore]
        public string ProfileImageUri { set; get; }

        public string LabelColor { set; get; }

        public int CompareTo(StatusInfo other)
        {
            return BigInteger.Parse(Id).CompareTo(BigInteger.Parse(other.Id));
        }
        public bool Equals(StatusInfo other)
        {
            return Id == other.Id && Text == other.Text;
        }
        public override bool Equals(object obj)
        {
            if (obj is StatusInfo)
            {
                return Equals((StatusInfo)obj);
            }
            else if (obj is BigInteger)
            {
                return BigInteger.Parse(Id) == (BigInteger)obj;
            }
            else if (obj is decimal)
            {
                return decimal.Parse(Id) == (decimal)obj;
            }
            else if (obj is string)
            {
                var s = (string)obj;
                return Id == s || Text == s;//stringはID or Textで判断
            }
            else
            {
                throw new ArgumentException();
            }
        }
        public override int GetHashCode()//テキトー実装
        {
            return Id.GetHashCode();
        }
    }

    public enum StatusTypes
    {
        Tweet,
        Retweet,
        Search,
        DirectMessage
    }
}
