using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

using EQNetwork.Utility;
using EQNetwork.Aspects;

namespace EQNetwork.Objects
{
    public class User : PropertyChangeTracker
    {
        // NotifyPropertyChanged is handled by PropertyChangeTracker to remember changes
        
        public enum SocialBits
        {
            VideosIWatch = 1,
            VideosIUpload = 2,
            VideosICommentOn = 4,
            VideosIShare = 8,
            ChannelsIFollow = 16,
            ChannelsICreate = 32,
            ChannelsIShare = 64,
            UsersIFollow = 128,
            VideosILike = 256,
            ChannelsILike = 512,
            UsersILike = 1024,
            VideosIFavorite = 2048,
        }


        // fields that can be set on the backend 
        [TrackPropertyChanged()]
        public string Username { get; set; }
        [TrackPropertyChanged()] 
        public string Password { get; set; }
        [TrackPropertyChanged()]
        public string Company { get; set; }
        [TrackPropertyChanged()]
        public string FirstName { get; set; }
        [TrackPropertyChanged()]
        public string LastName { get; set; }
        [TrackPropertyChanged()]
        public string Email { get; set; }
        [TrackPropertyChanged()]
        public DateTime? DateOfBirth { get; set; }
        [TrackPropertyChanged()]
        public string Gender { get; set; }
        [TrackPropertyChanged()]
        public string Phone { get; set; }
        [TrackPropertyChanged()]
        public string Carrier { get; set; }

        // social info
        [TrackPropertyChanged()]
        public bool? IsSocialOn { get; set; }
        [TrackPropertyChanged()]
        public long? FbBits { get; set; }
        [TrackPropertyChanged()]
        public long? TwitterBits { get; set; }

        // facebook
        public bool? FbIsLinked { get; private set; }
        public string FacebookId { get; private set; }
        public string FbAccessToken { get; private set; }
        public DateTime FbExpirationDate { get; private set; }

        // twitter
        public bool? TwitterIsLinked { get; private set; }
        public string TwitterUserId { get; private set; }
        public string TwitterScreenName { get; private set; }
        public string TwitterOAuthToken { get; private set; }
        public string TwitterOAuthTokenSecret { get; private set; }

        [TrackPropertyChanged()]
        [ReplaceNullWithInstanceOf(typeof(FileUploadSpec))]
        public FileUploadSpec Icon { private get; set; } // only one way serialization

        // not writeable
        public int? UserId { get; private set; }
        public bool? Active { get; private set; }
        public DateTime? Created { get; private set; }
        public DateTime? Modified { get; private set; }
        public int? UserTypeId { get; private set; }
        public string IconFilename { get; private set; }
        public bool? Verified { get; private set; }
        public Guid? ConfirmationGuid { get; private set; }
        public string AgreementAccepted { get; private set; }
        public DateTime? CreatedOn { get; private set; }
        public int? MembershipTypeId { get; private set; }
        public DateTime? MembershipExpiration { get; private set; }
        public long MembershipStorageLevelExpires { get; private set; }
        public long MembershipStorageLevel { get; private set; }
        public long MembershipStorageUsed { get; private set; }
        public DateTime? LastNotificationEmail { get; private set; }
        public DateTime? CurrentNotificationEmail { get; private set; }
        public long? MembershipStorageLevelEarned { get; private set; } 

        // helper enum conversion
        public Db.UserType UserType { get { return (UserTypeId == null) ? Db.UserType.Unknown : (Db.UserType)UserTypeId; } set { UserTypeId = (int)value; } }
        public Db.MembershipType MembershipType { get { return (MembershipTypeId == null) ? Db.MembershipType.Unknown : (Db.MembershipType)MembershipTypeId; } set { MembershipTypeId = (int)value; } }

        // calculated results from the backend
        public int? UnviewedCount { get; private set; }
        public bool? FollowedBy { get; private set; }
        public bool? Blocked { get; private set; }
        public bool? Following { get; private set; }
        public int? Followers { get; private set; }
        public int? ChannelFollowers { get; private set; }
        public string UserTitle { get; private set; }

        public User()
        {
        }

        public User(XmlNode node)
        {
            EQParse.SetPropertiesWithXmlAttributes(this, node);
            ClearPropertyChanges();
        }

        public override string ToString()
        {
            return Username;
        }

        public static User Parse(System.Net.WebResponse response)
        {
            return new User(EQNetwork.Services.EQApiService.ParseXml(response).FirstChild);
        }

        public static List<User> ParseList(PagingParameters pagingParameters, System.Net.WebResponse response)
        {
            XmlNode root = EQNetwork.Services.EQApiService.ParseXml(response);

            List<User> list = new List<User>();
            bool hasMore = false;

            foreach (XmlNode node in root.ChildNodes)
            {
                if (node.Name.Equals("Users", StringComparison.OrdinalIgnoreCase))
                {
                    int n = node.ChildNodes.Count;
                    if (pagingParameters != null)
                    {
                        // we always ask for one extra when paging
                        hasMore = (n > pagingParameters.PageSize);
                        if (hasMore) n--;
                    }
                    else
                        hasMore = false;
                    for (int i = 0; i < n; i++)
                        list.Add(new User(node.ChildNodes[i]));
                }
            }
            if (pagingParameters != null)
                pagingParameters.hasMore = hasMore;
            return list;
        }
    }
}
