using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;

using BeWo.ServiceProxy;
using BeWo.Scheduler.Resources;
using BeWo.Scheduler.View;

using DevExpress.Xpf.Scheduler;
using DevExpress.XtraScheduler;

namespace BeWo.Scheduler.ViewModel
{
    public class EmployeeAbsenceTimeListVM : AbstractAppointmentListVM<AbsenceTimeDC, AbsenceTimeAppointmentVM>
    {
        private readonly List<AbsenceReasonDC> mAllReasons;
        private readonly List<CompactEmployeeDC> mAllEmployees;
        private Dictionary<long, int> mReasonOid2CategoryIndex;

        public EmployeeAbsenceTimeListVM(List<AbsenceReasonDC> allReasons, List<CompactEmployeeDC> allemps, IEnumerable<AbsenceTimeDC> absenceTimes)
            : base(absenceTimes)
        {
            mAllReasons = allReasons;
            mAllEmployees = allemps;
			
            InitViewModel();
        }

        private new void InitViewModel()
        {
            foreach (var item in VMList)
                item.CustomFields.Add("EmployeeOid", item.EmployeeOid);

            base.InitViewModel();
        }

        protected override void InitCategoryList(List<BeWoAppointmentCategory> categoryList)
        {
            mReasonOid2CategoryIndex = new Dictionary<long, int>();

            int index = 0;
            foreach (var item in mAllReasons)
            {
                var solidColorBrush = (SolidColorBrush) new BrushConverter().ConvertFrom(item.Color);
				

                if (solidColorBrush != null)
                {
                    var cat = new BeWoAppointmentCategory
                    {
                        CategoryObject = item,
                        Color = solidColorBrush.Color,
                        DisplayName = item.Description,
                        MenuCaption = item.Description
                    };

                    categoryList.Add(cat);
                }

                if (item.AbsenceReasonOid.HasValue && !mReasonOid2CategoryIndex.ContainsKey(item.AbsenceReasonOid.Value))
                    mReasonOid2CategoryIndex.Add(item.AbsenceReasonOid.Value, index++);
            }
        }

        protected override void InitResourceList(List<IBeWoAppointmentResource> resourceList)
        {
			if (mAllEmployees != null)
				resourceList.AddRange(mAllEmployees.Select(item => new EmployeeResource(item)));
        }

	    protected override void UpdateResourceList(List<IBeWoAppointmentResource> resourceList, long pOid)
	    {
		    if (mAllEmployees == null) return;

		    resourceList.Clear();
		    resourceList.Add(new EmployeeResource(mAllEmployees.Find(x => x.EmployeeOid.Equals(pOid))));
	    }

	    protected override void InitAppointmentList()
        {
            foreach (var item in VMList)
            {
                item.ResourceId = item.DataContract.EmployeeOid;
				if (item.Reason.AbsenceReasonOid.HasValue && mReasonOid2CategoryIndex.ContainsKey(item.Reason.AbsenceReasonOid.Value))
                    item.LabelId = mReasonOid2CategoryIndex[item.Reason.AbsenceReasonOid.Value];
            }
        }

        protected override IBeWoAppointment CreateNewAppointmentVM()
        {
            var dc = new AbsenceTimeDC();

            return new AbsenceTimeAppointmentVM(dc);
        }

        protected override void UpdateAppointment(Appointment app, AbsenceTimeAppointmentVM vm)
        {
            //Update Resource
            long? oid = null;

            if (vm.ResourceId != null)
                oid = (long)vm.ResourceId;
            vm.EmployeeOid = oid;

            //Update Category
            AbsenceReasonDC reason = null;
            if (Categories != null)
            {
                if (vm.LabelId >= 0 && vm.LabelId < Categories.Count)
                {
                    var bcat = Categories[vm.LabelId];
                    reason = bcat.CategoryObject as AbsenceReasonDC;
                    vm.AppointmentCategory = bcat;
                }
            }

            vm.Reason = reason;
        }

        public override SchedulerSettings GetDefaultSchedulerSettings()
        {
            var settings = new SchedulerSettings(AppointmentKind.Resource, AppointmentViewType.Timeline) { GroupByResource = true };

            return settings;
        }

        public override AbstractAppointmentEditForm GetEditAppointmentForm(SchedulerControl control, Appointment appointment)
        {
            CompactEmployeeDC emp = null;
            if (appointment.ResourceId == null) 
                return new AbsenceTimeEditForm(control, appointment, null);

            var oid = (long) appointment.ResourceId;

            foreach (var item in mAllEmployees.Where(item => item.EmployeeOid == oid))
                emp = item;

            return new AbsenceTimeEditForm(control, appointment, emp);
        }

        protected override void SaveAppointments(List<AbsenceTimeDC> dcList)
        {
	        var erg = new List<AbsenceTimeDC>();
			ServiceFacade.DoCustomerServiceSync(s => erg = s.UpdateAbsenceTimes(dcList));
			UpdateViewModel(erg);
        }

        protected override void DeleteAppointments(IEnumerable<AbsenceTimeDC> dcList)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.DeactivateAbsenceTimes(dcList.ToDictionary(dc => dc.AbsenceTimeOid != null ? dc.AbsenceTimeOid.Value : 0,
                                                                  dc => dc.AbsenceTimeVersion != null ? dc.AbsenceTimeVersion.Value : 0)));
        }

        protected override void InsertNewAppointments(List<AbsenceTimeDC> dcList)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.InsertAbsenceTimes(dcList), UpdateViewModel);
        }

        public override void AddCustomFieldsMapping(SchedulerStorage schedulerStorage)
        {
            var employeeMapping = new SchedulerCustomFieldMapping("EmployeeOid", "EmployeeOid");
            schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(employeeMapping);
        }

        public override void InitNewAppointment(Appointment appointment)
        {
            appointment.CustomFields["EmployeeOid"] = null;
            appointment.StatusId = 0;
        }

		public override bool FilterAppointment(string filterCategory, object selectedObject, Appointment appointment, TimeInterval interval)
        {
	        if (selectedObject == null) return false;

			UpdateResourceList(Resources.ToList(), ((CompactEmployeeDC) selectedObject).EmployeeOid);

            return !((CompactEmployeeDC) selectedObject).EmployeeOid.Equals(appointment.CustomFields["EmployeeOid"]);
        }
    }
}