using System;
using System.Reflection;

namespace InABox.Core
{
    public class UserTrackingAttribute : Attribute
    {
        public UserTrackingAttribute(bool enabled)
        {
            Enabled = enabled;
            Parent = null;
            Alias = "";
        }

        public UserTrackingAttribute(Type parent)
        {
            Enabled = true;
            Parent = parent;
            Alias = "";
        }

        public UserTrackingAttribute(string alias)
        {
            Enabled = true;
            Parent = null;
            Alias = alias;
        }

        public bool Enabled { get; }

        public Type Parent { get; }

        public string Alias { get; }

        public static string TrackingName(Type type)
        {
            var attr = type.GetCustomAttribute<UserTrackingAttribute>();

            if (attr == null)
                return type.Name;

            if (!attr.Enabled)
                return null;

            if (attr.Parent != null)
                return TrackingName(attr.Parent);

            return attr.Alias;
        }

        public static Type TrackingType(Type type)
        {
            var attr = type.GetCustomAttribute<UserTrackingAttribute>();

            if (attr == null)
                return type;

            if (!attr.Enabled)
                return null;

            if (attr.Parent != null)
                return TrackingType(attr.Parent);

            return type;
        }
    }

    [UserTracking(false)]
    public class UserTracking : Entity, IRemotable, IPersistent, ILicense<CoreLicense>
    {
        [EntityRelationship(DeleteAction.Cascade)]
        public UserLink User => InitializeField(ref _user, nameof(User));
        private UserLink? _user;

        public DateTime Date { get; set; }

        public string Type { get; set; }

        public int Hour00Read { get; set; }
        public int Hour01Read { get; set; }
        public int Hour02Read { get; set; }
        public int Hour03Read { get; set; }
        public int Hour04Read { get; set; }
        public int Hour05Read { get; set; }
        public int Hour06Read { get; set; }
        public int Hour07Read { get; set; }
        public int Hour08Read { get; set; }
        public int Hour09Read { get; set; }
        public int Hour10Read { get; set; }
        public int Hour11Read { get; set; }
        public int Hour12Read { get; set; }
        public int Hour13Read { get; set; }
        public int Hour14Read { get; set; }
        public int Hour15Read { get; set; }
        public int Hour16Read { get; set; }
        public int Hour17Read { get; set; }
        public int Hour18Read { get; set; }
        public int Hour19Read { get; set; }
        public int Hour20Read { get; set; }
        public int Hour21Read { get; set; }
        public int Hour22Read { get; set; }
        public int Hour23Read { get; set; }

        public int TotalRead { get; set; }

        public int Hour00Write { get; set; }
        public int Hour01Write { get; set; }
        public int Hour02Write { get; set; }
        public int Hour03Write { get; set; }
        public int Hour04Write { get; set; }
        public int Hour05Write { get; set; }
        public int Hour06Write { get; set; }
        public int Hour07Write { get; set; }
        public int Hour08Write { get; set; }
        public int Hour09Write { get; set; }
        public int Hour10Write { get; set; }
        public int Hour11Write { get; set; }
        public int Hour12Write { get; set; }
        public int Hour13Write { get; set; }
        public int Hour14Write { get; set; }
        public int Hour15Write { get; set; }
        public int Hour16Write { get; set; }
        public int Hour17Write { get; set; }
        public int Hour18Write { get; set; }
        public int Hour19Write { get; set; }
        public int Hour20Write { get; set; }
        public int Hour21Write { get; set; }
        public int Hour22Write { get; set; }
        public int Hour23Write { get; set; }

        public int TotalWrite { get; set; }

        public void Increment(DateTime date, UserTrackingAction action)
        {
            var name = string.Format("Hour{0:D2}{1}", date.Hour, action.ToString());
            var property = GetType().GetProperty(name);
            var value = (int)property.GetValue(this);
            property.SetValue(this, value + 1);
        }

        protected override void DoPropertyChanged(string name, object? before, object? after)
        {
            base.DoPropertyChanged(name, before, after);
            TotalRead = Hour00Read + Hour01Read + Hour02Read + Hour03Read + Hour04Read + Hour05Read + Hour06Read + Hour07Read + Hour08Read +
                        Hour09Read + Hour10Read + Hour11Read + Hour12Read + Hour13Read + Hour14Read + Hour15Read + Hour16Read + Hour17Read +
                        Hour18Read + Hour19Read + Hour20Read + Hour21Read + Hour22Read + Hour23Read;
            TotalWrite = Hour00Write + Hour01Write + Hour02Write + Hour03Write + Hour04Write + Hour05Write + Hour06Write + Hour07Write + Hour08Write +
                         Hour09Write + Hour10Write + Hour11Write + Hour12Write + Hour13Write + Hour14Write + Hour15Write + Hour16Write + Hour17Write +
                         Hour18Write + Hour19Write + Hour20Write + Hour21Write + Hour22Write + Hour23Write;
        }
    }
}