using Csla;
using SyncfusionSchedulerDeleteBug.Business.Interfaces;
using SyncfusionSchedulerDeleteBug.DataAccess.Events;
using System;

namespace SyncfusionSchedulerDeleteBug.Business.Events
{
    [Serializable]
    public class CalendarEventInfo : BusinessBase<CalendarEventInfo>, IHoldCalendarEventInfo, IHoldOffsetDates
    {
        #region properties

        public readonly static PropertyInfo<int> IdProperty = RegisterProperty<int>(nameof(Id));
        public int Id
        {
            get { return GetProperty(IdProperty); }
            set { LoadProperty(IdProperty, value); }
        }

        public readonly static PropertyInfo<int> WorkerIdProperty = RegisterProperty<int>(nameof(WorkerId));
        public int WorkerId
        {
            get { return GetProperty(WorkerIdProperty); }
            set { LoadProperty(WorkerIdProperty, value); }
        }

        public readonly static PropertyInfo<string> WorkersFullNameProperty = RegisterProperty<string>(nameof(WorkersFullName));
        public string WorkersFullName
        {
            get { return GetProperty(WorkersFullNameProperty); }
            set { LoadProperty(WorkersFullNameProperty, value); }
        }

        public readonly static PropertyInfo<string> SubjectProperty = RegisterProperty<string>(nameof(Subject));
        public string Subject
        {
            get { return GetProperty(SubjectProperty); }
            set { LoadProperty(SubjectProperty, value); }
        }

        public readonly static PropertyInfo<string> TypeProperty = RegisterProperty<string>(nameof(Type));
        public string Type
        {
            get { return GetProperty(TypeProperty); }
            set { LoadProperty(TypeProperty, value); }
        }

        public readonly static PropertyInfo<int> CompanyIdProperty = RegisterProperty<int>(nameof(CompanyId));
        public int CompanyId
        {
            get { return GetProperty(CompanyIdProperty); }
            set { LoadProperty(CompanyIdProperty, value); }
        }

        public readonly static PropertyInfo<string> CompanyNameProperty = RegisterProperty<string>(nameof(CompanyName));
        public string CompanyName
        {
            get { return GetProperty(CompanyNameProperty); }
            set { LoadProperty(CompanyNameProperty, value); }
        }

        public readonly static PropertyInfo<int> ProjectIdProperty = RegisterProperty<int>(nameof(ProjectId));
        public int ProjectId
        {
            get { return GetProperty(ProjectIdProperty); }
            set { LoadProperty(ProjectIdProperty, value); }
        }

        public readonly static PropertyInfo<string> ProjectNameProperty = RegisterProperty<string>(nameof(ProjectName));
        public string ProjectName
        {
            get { return GetProperty(ProjectNameProperty); }
            set { LoadProperty(ProjectNameProperty, value); }
        }

        public readonly static PropertyInfo<int> CountryIdProperty = RegisterProperty<int>(nameof(CountryId));
        public int CountryId
        {
            get { return GetProperty(CountryIdProperty); }
            set { LoadProperty(CountryIdProperty, value); }
        }

        public readonly static PropertyInfo<string> CountryProperty = RegisterProperty<string>(nameof(Country));
        public string Country
        {
            get { return GetProperty(CountryProperty); }
            set { LoadProperty(CountryProperty, value); }
        }

        public readonly static PropertyInfo<string> LocationProperty = RegisterProperty<string>(nameof(Location));
        public string Location
        {
            get { return GetProperty(LocationProperty); }
            set { LoadProperty(LocationProperty, value); }
        }

        public readonly static PropertyInfo<DateTime> StartDateTimeProperty = RegisterProperty<DateTime>(nameof(StartTime));
        public DateTime StartTime
        {
            get { return GetProperty(StartDateTimeProperty); }
            set { LoadProperty(StartDateTimeProperty, value); }
        }

        public readonly static PropertyInfo<DateTime> EndDateTimeProperty = RegisterProperty<DateTime>(nameof(EndTime));
        public DateTime EndTime
        {
            get { return GetProperty(EndDateTimeProperty); }
            set { LoadProperty(EndDateTimeProperty, value); }
        }

        public readonly static PropertyInfo<DateTime> RecurrenceEndTimeProperty = RegisterProperty<DateTime>(nameof(LastOccurenceDate));
        public DateTime LastOccurenceDate
        {
            get { return GetProperty(RecurrenceEndTimeProperty); }
            set { LoadProperty(RecurrenceEndTimeProperty, value); }
        }

        public bool CurrentTimeMatchesLocal => StartTime.Equals(TimezoneStartTime);

        public readonly static PropertyInfo<DateTime> TimezoneStartTimeProperty = RegisterProperty<DateTime>(nameof(TimezoneStartTime));
        public DateTime TimezoneStartTime
        {
            get { return GetProperty(TimezoneStartTimeProperty); }
            set { LoadProperty(TimezoneStartTimeProperty, value); }
        }

        public readonly static PropertyInfo<TimeSpan> StartTimeOffsetProperty = RegisterProperty<TimeSpan>(nameof(StartTimeOffset));
        public TimeSpan StartTimeOffset
        {
            get { return GetProperty(StartTimeOffsetProperty); }
            set { LoadProperty(StartTimeOffsetProperty, value); }
        }

        public readonly static PropertyInfo<DateTime> TimezoneEndTimeProperty = RegisterProperty<DateTime>(nameof(TimezoneEndTime));
        public DateTime TimezoneEndTime
        {
            get { return GetProperty(TimezoneEndTimeProperty); }
            set { LoadProperty(TimezoneEndTimeProperty, value); }
        }

        public readonly static PropertyInfo<TimeSpan> EndTimeOffsetProperty = RegisterProperty<TimeSpan>(nameof(EndTimeOffset));
        public TimeSpan EndTimeOffset
        {
            get { return GetProperty(EndTimeOffsetProperty); }
            set { LoadProperty(EndTimeOffsetProperty, value); }
        }

        public readonly static PropertyInfo<string> DescriptionProperty = RegisterProperty<string>(nameof(Description));
        public string Description
        {
            get { return GetProperty(DescriptionProperty); }
            set { LoadProperty(DescriptionProperty, value); }
        }

        public readonly static PropertyInfo<bool> IsAllDayProperty = RegisterProperty<bool>(nameof(IsAllDay));
        public bool IsAllDay
        {
            get { return GetProperty(IsAllDayProperty); }
            set { LoadProperty(IsAllDayProperty, value); }
        }

        public bool IsRecurring
        {
            get { return !String.IsNullOrEmpty(RecurrenceRule); }
        }

        public readonly static PropertyInfo<int?> RecurrenceIDProperty = RegisterProperty<int?>(nameof(RecurrenceID));
        public int? RecurrenceID
        {
            get { return GetProperty(RecurrenceIDProperty); }
            set { LoadProperty(RecurrenceIDProperty, value); }
        }

        public readonly static PropertyInfo<string> RecurrenceRuleProperty = RegisterProperty<string>(nameof(RecurrenceRule));
        public string RecurrenceRule
        {
            get { return GetProperty(RecurrenceRuleProperty); }
            set { LoadProperty(RecurrenceRuleProperty, value); }
        }

        public readonly static PropertyInfo<string> RecurrenceExceptionProperty = RegisterProperty<string>(nameof(RecurrenceException));
        public string RecurrenceException
        {
            get { return GetProperty(RecurrenceExceptionProperty); }
            set { LoadProperty(RecurrenceExceptionProperty, value); }
        }    

        public readonly static PropertyInfo<string> BackgroundColorProperty = RegisterProperty<string>(nameof(BackgroundColor));
        public string BackgroundColor
        {
            get { return GetProperty(BackgroundColorProperty); }
            set { LoadProperty(BackgroundColorProperty, value); }
        }

        public readonly static PropertyInfo<string> ForegroundColorProperty = RegisterProperty<string>(nameof(ForegroundColor));
        public string ForegroundColor
        {
            get { return GetProperty(ForegroundColorProperty); }
            set { LoadProperty(ForegroundColorProperty, value); }
        }

        public bool OffsetApplied { get; private set; }

        #endregion

        #region business methods

        public void ApplyUserOffset(TimeSpan userOffset)
        {
            if (OffsetApplied)
                return;

            //event is for UTC + 2 timezone.
            //user's pc is for UTC + 5 timezone.
            //respective to the user, the event is -3 hours
            //10:00 - 11:00 is 13:00 - 14:00 for this user. Adjust the offset to be -3
            StartTime = TimezoneStartTime.ApplyOffset(StartTimeOffset - userOffset).UtcDateTime;
            EndTime = TimezoneEndTime.ApplyOffset(EndTimeOffset - userOffset).UtcDateTime;

            OffsetApplied = true;
        }

        #endregion

        #region data access

        [CreateChild]
        private void Create(CalendarEventInfoDto eventDto)
        {
            Fetch(eventDto);
        }

        [FetchChild]
        private void Fetch(CalendarEventInfoDto eventDto)
        {
            if (eventDto is null)
                return;

            Id = eventDto.Id;
            Type = eventDto.TypeDescription;
            WorkerId = eventDto.WorkerId;
            WorkersFullName = eventDto.WorkersFullName;
            Subject = eventDto.Title;
            CompanyId = eventDto.CompanyId;
            CompanyName = eventDto.CompanyName;
            ProjectId = eventDto.ProjectId;            

            if (ProjectId == 0)
            {
                ProjectId = -1;
                ProjectName = "Unassigned";

            } else { ProjectName = eventDto.ProjectName; }

            CountryId = eventDto.CountryId;
            Country = eventDto.Country;
            Location = eventDto.Location;
            Description = eventDto.Summary;
            BackgroundColor = eventDto.BackgroundColor;

            if (!string.IsNullOrEmpty(eventDto.ForegroundColor))
            {
                ForegroundColor = eventDto.ForegroundColor;
            }
            else
            {
                ForegroundColor = "#FFFFFF";
            }

            //calendar is bound to these
            StartTime = eventDto.DStart.LocalDateTime;
            EndTime = eventDto.DEnd.LocalDateTime;

            //Time without offset applied
            TimezoneStartTime = eventDto.DStart.DateTime;
            StartTimeOffset = eventDto.DStart.Offset;
            TimezoneEndTime = eventDto.DEnd.DateTime;
            EndTimeOffset = eventDto.DEnd.Offset;

            IsAllDay = eventDto.IsAllDay;

            if (!string.IsNullOrEmpty(eventDto.RecurrenceRule))
            {
                RecurrenceRule = eventDto.RecurrenceRule;
            }            
            else
            {
                RecurrenceRule = string.Empty;
            }

            if (!string.IsNullOrEmpty(eventDto.RecurrenceException))
            {
                RecurrenceException = eventDto.RecurrenceException;
            }
            else
            {
                RecurrenceException = string.Empty;
            }

            RecurrenceID = eventDto.RecurrenceId;

            if (eventDto.LastOccurenceDate is null)
                LastOccurenceDate = EndTime;
            else
                LastOccurenceDate = eventDto.LastOccurenceDate.GetValueOrDefault();
        }       
        
        #endregion
    }
}
