using System;
using System.Linq;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Data.Services.Client;
using PhoneAppOData.NWServiceReference;
using System.Text;
using System.Collections.Generic;


namespace PhoneAppOData
{
    public partial class MainPage : PhoneApplicationPage
    {
        private NorthwindEntities context;
        
        private readonly Uri northwindUri =
            new Uri("http://services.odata.org/Northwind/Northwind.svc/");
        private DataServiceCollection<Customer> customers;

        private bool isDataLoaded = false;


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

        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            LoadData();
        }


        private void LoadData()
        {
            // Initialize the context and the binding collection. 
            context = new NorthwindEntities(northwindUri);
            customers = new DataServiceCollection<Customer>(context);


            var query = from custo in context.Customers.Expand("Orders")
                        select custo;

            // Register for the LoadCompleted event.
            customers.LoadCompleted += customers_LoadCompleted;

            // Load the customers feed by executing the LINQ query.
            customers.LoadAsync(context.Customers);

        }
        
        void customers_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                // Handling for a paged data feed.
                if (customers.Continuation != null)
                {
                    // Automatically load the next page.
                    customers.LoadNextPartialSetAsync();
                }
                else
                {
                    // Set the data context of the list box control to the sample data.
                    this.LayoutRoot.DataContext = customers;
                    this.isDataLoaded = true;

                }
            }
            else
            {
                MessageBox.Show(string.Format("An error has occurred: {0}", e.Error.Message));
            }
        }
        #region Save Data
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            customers[0].City = "Essen";
            context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context);
        }

        StringBuilder error;
        private void OnChangesSaved(IAsyncResult result)
        {
            // Use the Dispatcher to ensure that the 
            // asynchronous call returns in the correct thread.
            Dispatcher.BeginInvoke(() =>
            {
                context = result.AsyncState as NorthwindEntities;
                error = new StringBuilder();
                try
                {
                    // Complete the save changes operation and display the response.
                    WriteOperationResponse(context.EndSaveChanges(result));
                }
                catch (DataServiceRequestException ex)
                {
                    // Display the error from the response.
                    WriteOperationResponse(ex.Response);
                }
                catch (InvalidOperationException ex)
                {
                    error.Append(ex.Message);
                }
            }
            );
        }
        private void WriteOperationResponse(DataServiceResponse response)
        {
            int i = 1;

            if (response.IsBatchResponse)
            {
                error.AppendLine(string.Format("Batch operation response code: {0}\n",
                    response.BatchStatusCode));
            }
            foreach (ChangeOperationResponse change in response)
            {
                error.AppendLine(
                    string.Format("\tChange {0} code: {1}\n",
                    i.ToString(), change.StatusCode.ToString()));
                if (change.Error != null)
                {
                    error.AppendLine(
                    string.Format("\tChange {0} error: {1}\n",
                        i.ToString(), change.Error.Message));
                }
                i++;
            }
            MessageBox.Show(error.ToString());
        }
        #endregion

        #region Persist Data
        protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            // Define a dictionary to hold an existing 
            // DataServiceCollection<Customer>. 
            var collections = new Dictionary<string, object>();
            collections.Add("Customers", customers);

            // Serialize the data service data and store it in the page state.      
            this.State["DataServiceState"] =
                DataServiceState.Serialize(context, collections);
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            // Get the object data if it is not still loaded.
            if (!this.isDataLoaded)
            {
                object storedState;
                DataServiceState state;

                // Try to get the serialized data service state.
                if (this.State.TryGetValue("DataServiceState", out storedState))
                {
                    // Deserialize the DataServiceState object.
                    state = DataServiceState.Deserialize(storedState as string);

                    // Set the context from the stored object.
                    var restoredContext = (NorthwindEntities)state.Context;

                    // Set the binding collections from the stored collection.
                    var restoredCustomers = state.RootCollections["Customers"]
                        as DataServiceCollection<Customer>;

                    // Use the returned data to load the page UI.
                    this.LoadData(restoredContext, restoredCustomers);
                }
                else
                {
                    // If we don't have any data stored, 
                    // we need to reload it from the data service.
                    this.LoadData();
                }
            }
        }
        // Display data from the stored data context and binding collection. 
        public void LoadData(NorthwindEntities context, DataServiceCollection<Customer> customers)
        {
            this.context = context;
            this.customers = customers;

            this.isDataLoaded = true;
        }
        #endregion
    }
}