using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using C1.Silverlight.Schedule;
using C1.C1Schedule;
using System.IO;
using C1.Silverlight.Data;
using DataBinding.DataService;

namespace DataBinding
{
    public partial class MainPage : UserControl
    {
        #region ** fields
        private DataSet _ds = null;
        private DataTable _dtAppointments = null;
        #endregion

        #region ** ctor
        public MainPage()
        {
            InitializeComponent();
            
            // set mappings for AppointmentStorage
            // (set mapping between AppointmentStorage and Appointment table columns)
            AppointmentMappingCollection mappings = sched1.DataStorage.AppointmentStorage.Mappings;
            mappings.IdMapping.MappingName = "Id";
            mappings.Subject.MappingName = "Subject";
            mappings.Body.MappingName = "Body";
            mappings.End.MappingName = "End";
            mappings.Start.MappingName = "Start";
            mappings.Location.MappingName = "Location";
            mappings.AppointmentProperties.MappingName = "Properties";
            
            // load actual data from server
            LoadData();
        }
        #endregion

        #region ** loading data
        // Get data service relative to current host/domain
        DataServiceSoapClient GetDataService()
        {
            // Increase buffer size
            var binding = new System.ServiceModel.BasicHttpBinding();
            binding.MaxReceivedMessageSize = 2147483647; // int.MaxValue
            binding.MaxBufferSize = 2147483647; // int.MaxValue

            // Get absolute service address
            Uri uri = C1.Silverlight.Extensions.GetAbsoluteUri("DataService.asmx");
            var address = new System.ServiceModel.EndpointAddress(uri);

            // Return new service client
            return new DataServiceSoapClient(binding, address);
        }
        
        void LoadData()
        {
            // Invoke Web service
            var svc = GetDataService();
            svc.GetDataCompleted += svc_GetDataCompleted;
            svc.GetDataAsync("Appointments");
        }

        void svc_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
        {
            // Handle errors
            if (e.Error != null)
            {
                tbStatus.Text = "Error downloading data...";
                return;
            }

            // Parse data stream from server (DataSet as XML)
            tbStatus.Text = string.Format(
              "Got data, {0:n0} kBytes", e.Result.Length / 1024);

            var ms = new MemoryStream(e.Result);
            _ds = new DataSet();
            _ds.EnforceConstraints = false;
            _ds.ReadXml(ms);
            _ds.EnforceConstraints = true;
            _ds.AcceptChanges();

            // Got the data, find the table
            _dtAppointments = _ds.Tables["Appointments"];

            // set C1Scheduler data source to the DataTable loaded from server
            sched1.DataStorage.AppointmentStorage.DataSource = _dtAppointments;

        }
        #endregion

        #region ** saving data
        private void btnCommit_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            // uncomment SaveData call to enable saving data to server
#if true
            string msg =
                "This functionality is disabled to prevent changes to the database on our site.\r\n" +
                "To see it in action, please download the Studio, " +
                "edit your local copy of DataBinding.MainPage.btnCommit_Click method according to the comments in code " + 
                "and run the sample locally.";
            MessageBox.Show(msg, "Functionality Disabled", MessageBoxButton.OK);
#else
            SaveData();
#endif
        }

        // Save data back into the database
        void SaveData()
        {
            if (_ds != null)
            {
                // get changes of each type
                byte[] dtAdded = GetChanges(DataRowState.Added);
                byte[] dtModified = GetChanges(DataRowState.Modified);
                byte[] dtDeleted = GetChanges(DataRowState.Deleted);

                // Invoke service
                var svc = GetDataService();
                svc.UpdateDataCompleted += svc_UpdateDataCompleted;
                svc.UpdateDataAsync(dtAdded, dtModified, dtDeleted);
            }
        }

        void svc_UpdateDataCompleted(object sender, UpdateDataCompletedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Result))
            {
                throw new Exception("Error updating data on the server: " + e.Result);
            }

            tbStatus.Text = "Changes accepted by server.";
            _ds.AcceptChanges();
        }

        byte[] GetChanges(DataRowState state)
        {
            DataSet ds = _ds.GetChanges(state);
            if (ds != null)
            {
                MemoryStream ms = new MemoryStream();
                ds.WriteXml(ms);
                return ms.ToArray();
            }
            return null;
        }
        #endregion

        #region ** navigation
        private void btnToday_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.VisibleDates.BeginUpdate();
            sched1.VisibleDates.Clear();
            sched1.VisibleDates.Add(DateTime.Today);
            sched1.VisibleDates.EndUpdate();
        }

        private void btnDay_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.ChangeStyle(sched1.OneDayStyle);
        }

        private void btnWorkWeek_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.ChangeStyle(sched1.WorkingWeekStyle);
        }

        private void btnWeek_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.ChangeStyle(sched1.WeekStyle);
        }

        private void btnMonth_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.ChangeStyle(sched1.MonthStyle);
        }
        
        private void btnTimeLine_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            sched1.ChangeStyle(sched1.TimeLineStyle);
        }
        #endregion

        #region ** import/export
        private void btnImport_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            C1Scheduler.ImportCommand.Execute(null, sched1);
        }

        private void btnExport_Click(object sender, C1.Silverlight.SourcedEventArgs e)
        {
            C1Scheduler.ExportCommand.Execute(null, sched1);
        }
        #endregion
    }
}
