using System;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Olap;

namespace SqlFilter
{
    public partial class MainPage : UserControl
    {
        const string DEFAULT_VIEW = "DEFAULT_VIEW";
        const string DEFAULT_CUSTOMERS = "Hanari Carnes|Hungry Coyote Import Store|Island Trading|Laughing Bacchus Wine Cellars|Rancho grande|La maison d'Asie|La corne d'abondance";

        ObservableCollection<string> _allCustomers;
        ObservableCollection<NorthwindDataServiceReference.Invoice> _invoices;
        C1OlapFilter _customerFilter;

        public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            // initialize OlapPage data source 
            _invoices = new ObservableCollection<SqlFilter.NorthwindDataServiceReference.Invoice>();
            _c1OlapPage.DataSource = _invoices;

            // initialize view
            var userSettings = IsolatedStorageSettings.ApplicationSettings;
            if (userSettings.Contains(DEFAULT_VIEW))
            {
                // get list of customers that were in view last time
                _c1OlapPage.ViewDefinition = userSettings[DEFAULT_VIEW] as string;
            }
            else
            {
                // initialize selected customer list
                var selectedCustomers = new List<string>();
                foreach (string s in DEFAULT_CUSTOMERS.Split('|'))
                {
                    selectedCustomers.Add(s);
                }

                // initialize OlapPage view
                var olap = _c1OlapPage.OlapEngine;
                olap.BeginUpdate();
                olap.ColumnFields.Add("OrderDate");
                olap.RowFields.Add("CustomerName");
                olap.ValueFields.Add("ExtendedPrice");
                olap.RowFields[0].Width = 200;
                olap.Fields["OrderDate"].Format = "yyyy";
                olap.Fields["CustomerName"].Filter.ShowValues = selectedCustomers.ToArray();
                olap.EndUpdate();
            }

            // save current view to storage when closing the app
            Application.Current.Exit += (s, ea) =>
            {
                userSettings[DEFAULT_VIEW] = _c1OlapPage.ViewDefinition;
                userSettings.Save();
            };

            // get list of all customers in the database
            var sc = new SqlFilter.NorthwindDataServiceReference.NorthwindDataServiceClient();
            sc.GetCustomersCompleted += sc_GetCustomersCompleted;
            sc.GetCustomersAsync();

            // show status
            _lblStatus.Text = "Retrieving customer list...";
        }

        // got complete list of customers in the database: store it, show it in filter, and listen for changes
        void sc_GetCustomersCompleted(object sender, SqlFilter.NorthwindDataServiceReference.GetCustomersCompletedEventArgs e)
        {
            // hide 'loading' message
            _lblLoading.Visibility = Visibility.Collapsed;

            // monitor CustomerName filter
            _customerFilter = _c1OlapPage.OlapEngine.Fields["CustomerName"].Filter;
            _customerFilter.PropertyChanged += filter_PropertyChanged;

            // monitor view definition to ensure CustomerName field is always active
            _c1OlapPage.ViewDefinitionChanged += _c1OlapPage_ViewDefinitionChanged;

            // show available customers in the "CustomerName" field filter
            _allCustomers = e.Result;
            _customerFilter.Values = _allCustomers;

            // go get the data
            GetData();
        }

        // make sure Customer field is always in the view
        void _c1OlapPage_ViewDefinitionChanged(object sender, EventArgs e)
        {
            var olap = _c1OlapPage.OlapEngine;
            var field = olap.Fields["CustomerName"];
            if (!field.IsActive)
            {
                olap.FilterFields.Add(field);
            }
        }

        // CustomerName field filter has changed: get new data
        void filter_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            GetData();
        }

        // go get invoice data for the selected customers
        void GetData()
        {
            // re-create active customer list based on the current filter settings
            var selectedCustomers = new ObservableCollection<string>();
            foreach (string customer in _allCustomers)
            {
                if (_customerFilter.Apply(customer))
                {
                    selectedCustomers.Add(customer);
                }
            }
            _customerFilter.ShowValues = selectedCustomers.ToArray();

            // go get invoices for the selected customers
            var sc = new SqlFilter.NorthwindDataServiceReference.NorthwindDataServiceClient();
            sc.GetCustomerInvoicesCompleted += sc_GetCustomerInvoicesCompleted;
            sc.GetCustomerInvoicesAsync(selectedCustomers);

            // show status
            _lblStatus.Text = string.Format("Retrieving invoices for {0} customers...", selectedCustomers.Count);
        }

        // got new data: show it on C1OlapPage
        void sc_GetCustomerInvoicesCompleted(object sender, SqlFilter.NorthwindDataServiceReference.GetCustomerInvoicesCompletedEventArgs e)
        {
            if (e.Cancelled || e.Error != null)
            {
                _lblStatus.Text = string.Format("** Error: {0}", e.Error != null ? e.Error.Message : "Canceled");
            }
            else
            {
                _lblStatus.Text = string.Format("Received {0} invoices ({1} customers).",
                    e.Result.Count,
                    _customerFilter.ShowValues.Length);

                // begin update
                var olap = _c1OlapPage.OlapEngine;
                olap.BeginUpdate();

                // update data source
                _invoices.Clear();
                foreach (var invoice in e.Result)
                {
                    _invoices.Add(invoice);
                }

                // finish update
                olap.EndUpdate();
            }
        }

        // regenerate the olap view
        void Button_Click(object sender, RoutedEventArgs e)
        {
            _c1OlapPage.OlapPanel.OlapEngine.Update();
        }
    }
}
