using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Threading;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml;
using C1.Xaml.Calendar;
using Windows.UI.Popups;
using Windows.UI;
using Windows.ApplicationModel.Appointments;
using System.Threading.Tasks;

namespace CalendarDemo
{
    public partial class MainPage : Page
    {
        // Summary:
        //     Contains all available information about an individual appointment.
        //     For the demo purposes when run application in emulator and has no appointments from device
        public class Appointment
        {
            public Appointment()
            {
            }
            // Summary:
            //     Gets the date and time that the appointment ends.
            //
            // Returns:
            //     The date and time that the appointment ends.
            public DateTime EndTime { get; set; }
            //
            // Summary:
            //     Gets the date and time that the appointment starts.
            //
            // Returns:
            //     The date and time that the appointment starts.
            public DateTime StartTime { get; set; }
            //
            // Summary:
            //     Gets the subject of the appointment.
            //
            // Returns:
            //     The subject of the appointment.
            public string Subject { get; set; }
        }

        // If it is true, the sample will work with device's Appointments provider.
        // If it is false, the sample will bind collection of custom Appointment objects. 
        private static bool UseAppointmentManager = true;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        private void AlterAppearance_Click(object sender, RoutedEventArgs e)
        {
            // show Sundays in Red and Saturdays in Blue
            DaySlotTemplateSelector datesSelector = this.Resources["DaySlotTemplateSelector"] as DaySlotTemplateSelector;
            cal1.DaySlotTemplateSelector = datesSelector;
            // use bolded days dictionary defined in the DaySlotTemplateSelector class instance 
            cal1.DayOfWeekSlotTemplateSelector = new DayOfWeekTemplateSelector();
            cal1.WeekendBrush = new SolidColorBrush(Colors.Red);
            cal1.TodayBrush = new SolidColorBrush(Colors.Green);
            Refresh(cal1.DisplayDate);
        }

        private void cal1_Loaded(object sender, RoutedEventArgs e)
        {
            Refresh(cal1.DisplayDate);
        }

        private void Refresh(DateTime displayDate)
        {
            // update bolded dates for the visible month (and for adjacent days)
            GetBoldedDates(displayDate.AddMonths(-1), displayDate.AddMonths(2));
        }

        private void cal1_DisplayDateChanging(object sender, DateChangedEventArgs e)
        {
            Refresh(e.NewValue);
        }

        private async void cal1_DoubleTapped(object sender, RoutedEventArgs e)
        {
            // show the list of appointments for the bolded day
            FrameworkElement fel = e.OriginalSource as FrameworkElement;
            if (fel != null)
            {
                DaySlot slot = fel.DataContext as DaySlot;
                if (slot != null)
                {
                    DateTime date = slot.Date;
                    string message = date.ToString();
                    if (slot.DataSource == null || slot.DataSource.Count == 0)
                    {
                        if (UseAppointmentManager)
                        {
                            // create new appointment and fill initial properties
                            Windows.ApplicationModel.Appointments.Appointment app = new Windows.ApplicationModel.Appointments.Appointment();
                            app.StartTime = date;
                            app.AllDay = true;
                            // Show the Appointments provider Add Appointment UI, to enable the user to add an appointment. 
                            // The returned id can be used later to edit or remove existent appointment.
                            string id = await AppointmentManager.ShowAddAppointmentAsync(app, new Windows.Foundation.Rect());
                            Refresh(cal1.DisplayDate);
                            return;
                        }
                        else
                        {
                            message += "\r\nNo events for this day.";
                        }
                    }
                    else
                    {
                        if (!UseAppointmentManager)
                        {
                            foreach (Appointment app in slot.DataSource)
                            {
                                message += "\r\n" + app.Subject;
                            }
                        }
                        else
                        {
                            foreach (Windows.ApplicationModel.Appointments.Appointment app in slot.DataSource)
                            {
                                message += "\r\n" + app.Subject;
                            }
                        }
                        var dialog = new MessageDialog(message);
                        dialog.ShowAsync();
                    }
                }
            }
        }

        private async Task GetBoldedDates(DateTime start, DateTime end)
        {
            DateList boldedDates = cal1.BoldedDates;
            if (!UseAppointmentManager)
            {
                // generate test appointment
                List<object> list = new List<object>();
                Appointment app = new Appointment();
                app.StartTime = start.AddDays(12);
                app.EndTime = app.StartTime.AddHours(1);
                app.Subject = "test emulator appointment";
                list.Add(app);
                // bind calendar to data
                cal1.DataSource = list;
                // don't set StartTimePath and EndTimePath as they are the same as default values
            }
            else
            {
                // get appointments from the device calendar
                var store = await AppointmentManager.RequestStoreAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
                var appointments = await store.FindAppointmentsAsync(new DateTimeOffset(start), end - start);

                // bind calendar to the search results
                cal1.DataSource = appointments;
                // don't set StartTimePath and EndTimePath as they are the same as default values
            }
        }

        private void Help_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new MessageDialog("1. Tap to select single day.\r\n2. Tap or hold and slide finger to select several days.\r\n3. Double tap on bolded days to see details. \r\n4. Double tap on empty day to create new event in device calendar.");
            dialog.ShowAsync();
        }

        private void Today_Click(object sender, RoutedEventArgs e)
        {
            cal1.Today();
        }
    }

    public class DaySlotTemplateSelector : C1.Xaml.Calendar.DaySlotTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            DaySlot slot = item as DaySlot;
            if (slot != null && !slot.IsAdjacent && slot.DayOfWeek == DayOfWeek.Saturday)
            {
                // set color for Saturday
                ((Control)container).Foreground = new SolidColorBrush(Color.FromArgb(255, 0, 191, 255));
            }
            // the base class will select custom DataTemplate, defined in the DaySlotTemplateSelector.Resources collection (see MainPage.xaml file)
            return base.SelectTemplateCore(item, container);
        }
    }

    public class DayOfWeekTemplateSelector : C1.Xaml.C1DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            DayOfWeekSlot slot = item as DayOfWeekSlot;
            if (slot != null && slot.DayOfWeek == DayOfWeek.Saturday)
            {
                // set color for Saturday
                ((Control)container).Foreground = new SolidColorBrush(Color.FromArgb(255, 0, 191, 255));
            }
            // don't change DataTemplate at all
            return null;
        }
    }
}