using System;
using System.Collections.Generic;
using System.Linq;
using WebMail.Model;
using Telerik.Web.UI;

/// <summary>
/// Custom EntityFrameworkProvider for RadScheduler
/// </summary>
public class EntitySchedulerProvider : SchedulerProviderBase
{
    private IDictionary<int, Resource> _calendars;

    private IDictionary<int, Resource> Calendars
    {
        get
        {
            if (_calendars == null)
            {
                _calendars = new Dictionary<int, Resource>();
                foreach (Resource calendar in LoadCalendars())
                {
                    _calendars.Add((int)calendar.Key, calendar);
                }
            }

            return _calendars;
        }
    }

    public override IEnumerable<Appointment> GetAppointments(ISchedulerInfo schedulerInfo)
    {
        List<Appointment> appointments = new List<Appointment>();

        using (WebMailContext db = new WebMailContext())
        {
            appointments.AddRange(db.Events.ToList().Select(SchedulerHelper.AppointmentsResolver));
        }

        foreach (Appointment apt in appointments)
        {
            LoadResources(apt);
        }

        return appointments;
    }

    public override void Insert(ISchedulerInfo schedulerInfo, Appointment appointmentToInsert)
    {
        using (WebMailContext db = new WebMailContext())
        {
            string location = appointmentToInsert.Attributes["Location"] != null ? appointmentToInsert.Attributes["Location"].ToString() : string.Empty;
            string invitees = appointmentToInsert.Attributes["Invitees"] != null ? appointmentToInsert.Attributes["Invitees"].ToString() : string.Empty;

            Event newEvent = new Event()
            {
                Subject = appointmentToInsert.Subject,
                Start = appointmentToInsert.Start,
                End = appointmentToInsert.End,
                RecurrenceRule = appointmentToInsert.RecurrenceRule,
                RecurrenceParentID = appointmentToInsert.RecurrenceParentID as int?,
                Reminder = appointmentToInsert.Reminders.ToString(),
                TimeZoneID = appointmentToInsert.TimeZoneID,
                Location = location,
                Invitees = invitees
            };
         
            db.Events.Add(newEvent);

            foreach (Resource resource in appointmentToInsert.Resources)
            {
                EventCalendar eventCalendar = new EventCalendar();
                eventCalendar.EventId = newEvent.ID;
                eventCalendar.FolderId = db.Folders.Where(x => x.Name == resource.Text && x.Category == "Calendar").Select(x => x.Id).First();
                db.EventsCalendars.Add(eventCalendar);
            }

            db.SaveChanges();
        }
    }

    public override void Update(ISchedulerInfo schedulerInfo, Appointment appointmentToUpdate)
    {
        using (WebMailContext db = new WebMailContext())
        {
            Event eventToUpdate = db.Events.FirstOrDefault(x => x.ID == (Guid)appointmentToUpdate.ID);

            if (eventToUpdate != null)
            {
                eventToUpdate.Subject = appointmentToUpdate.Subject;
                eventToUpdate.Start = appointmentToUpdate.Start;
                eventToUpdate.End = appointmentToUpdate.End;
                eventToUpdate.RecurrenceRule = appointmentToUpdate.RecurrenceRule;
                eventToUpdate.RecurrenceParentID = appointmentToUpdate.RecurrenceParentID as int?;
                eventToUpdate.Reminder = appointmentToUpdate.Reminders.ToString();
                eventToUpdate.Location = appointmentToUpdate.Attributes["Location"].ToString();
                eventToUpdate.Invitees = appointmentToUpdate.Attributes["Invitees"].ToString();
            }

            db.SaveChanges();
        }
    }

    public override void Delete(ISchedulerInfo schedulerInfo, Appointment appointmentToDelete)
    {
        using (WebMailContext db = new WebMailContext())
        {
            Event eventToDelete = db.Events.FirstOrDefault(x => x.ID == (Guid)appointmentToDelete.ID);

            if (eventToDelete != null)
            {
                db.EventsCalendars.RemoveRange(db.EventsCalendars.Where(x => x.EventId == eventToDelete.ID));
                db.Events.Remove(eventToDelete);
            }

            db.SaveChanges();
        }
    }

    public override IEnumerable<ResourceType> GetResourceTypes(RadScheduler owner)
    {
        ResourceType[] resourceTypes = new ResourceType[2];
        resourceTypes[0] = new ResourceType("Calendar", true);

        return resourceTypes;
    }

    public override IDictionary<ResourceType, IEnumerable<Resource>> GetResources(ISchedulerInfo schedulerInfo)
    {
        Dictionary<ResourceType, IEnumerable<Resource>> resCollection = new Dictionary<ResourceType, IEnumerable<Resource>>();

        resCollection.Add(new ResourceType("Calendar", true), Calendars.Values);

        return resCollection;
    }

    public override IEnumerable<Resource> GetResourcesByType(RadScheduler owner, string resourceType)
    {
        switch (resourceType)
        {
            case "Calendar":
                return Calendars.Values;

            default:
                throw new InvalidOperationException("Unknown resource type: " + resourceType);
        }
    }

    public ReminderCollection GetReminderList(string reminder)
    {
        ReminderCollection reminders = null;

        return reminders;
    }

    public IEnumerable<Resource> LoadCalendars()
    {
        using (WebMailContext db = new WebMailContext())
        {
            return db.Folders.Where(x => x.Category == "Calendar").Select(SchedulerHelper.ResourcesResolver).ToList();
        }
    }

    public void LoadResources(Appointment apt)
    {
        using (WebMailContext db = new WebMailContext())
        {
            var aptResources = from ec in db.EventsCalendars
                               where ec.EventId.ToString() == apt.ID.ToString()
                               select ec;

            foreach (var aptResource in aptResources)
            {
                Resource calendar = Calendars[aptResource.FolderId];

                apt.Resources.Add(calendar);
            }
        }
    }
}