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.Data.Transactions;
using C1.Data;
using C1.Silverlight.Data.RiaServices;
using C1.LiveLinq.LiveViews;

namespace TransactionsSilverlight
{
    public partial class CustomerControl : UserControl
    {
        // This class is used as the result item type of an Order view defined below.
        public class OrderInfo
        {
            public OrderInfo(Web.Order o)
            {
                _order = o;
            }
            private Web.Order _order;
            public Web.Order GetOrder() { return _order; }

            public virtual int OrderID { get; set; }
            public virtual DateTime? OrderDate { get; set; }
            public virtual decimal? Freight { get; set; }
            public virtual string ShipName { get; set; }
            public virtual string ShipCity { get; set; }
        }

        // The customer being edited.
        public Web.Customer Customer { get; private set; }
        // This view contains the orders of the current customer.
        View _ordersView;
        // All changes in this control are made in the scope of this client transaction.
        ClientTransaction _transaction;
        RiaClientCache _cache;

        public CustomerControl()
        {
            InitializeComponent();
        }

        public CustomerControl(Web.Customer customer, RiaClientCache clientCache)
        {
            InitializeComponent();
            _cache = clientCache;
            Customer = customer;

            // Define and bind a live view of orders of the current customer.
            _ordersView = from o in customer.Orders.AsLive(_cache)
                          select new OrderInfo(o)
                          {
                              OrderID = o.OrderID,
                              OrderDate = o.OrderDate,
                              Freight = o.Freight,
                              ShipName = o.ShipName,
                              ShipCity = o.ShipCity
                          };
            CreateTransaction();
            ordersGrid.ItemsSource = _ordersView;
        }

        void transaction_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            // The Undo button is enabled if and only if there are changes made in the transaction scope.
            buttonUndo.IsEnabled = _transaction.HasChanges;
        }

        void CreateTransaction()
        {
            // Initialize the client transaction.
            // Specify that all changes to _ordersView are automatically considered changes made in the scope of this transaction.
            _transaction = _cache.CreateTransaction();
            _ordersView.SetTransaction(_transaction);

            // Enable/disable the Undo button when the _transaction.HasChanges property value changes.
            _transaction.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(transaction_PropertyChanged);
            buttonUndo.IsEnabled = false;
        }

        void undo_Click(object sender, RoutedEventArgs e)
        {
            // Cancel the changes made by this control
            // by rolling back the transaction.
            _transaction.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(transaction_PropertyChanged);
            _transaction.Rollback();
            // Create a new transaction.
            CreateTransaction();
        }

        private void close_Click(object sender, RoutedEventArgs e)
        {
            if (_transaction.HasChanges)
            {
                // Ask the user whether they will save or cancel the changes made by this control.
                switch (MessageBox.Show("Do you want to save changes?", "", MessageBoxButton.OKCancel))
                {
                    case MessageBoxResult.OK:
                        _transaction.Commit();
                        break;
                    case MessageBoxResult.Cancel:
                        return;
                }
            }
            // Raise the CloseRequested event, so MainForm can remove the tab page containing this control.
            CloseRequested(this, EventArgs.Empty);
        }

        // MainForm closes the tab page with this control when this event is raised.
        public event EventHandler CloseRequested = delegate { };

        private void addOrder(object sender, RoutedEventArgs e)
        {
            // Add a new Order.
            var order = new Web.Order();
            var window = new OrderWindow(order, _cache, _transaction, Customer);
            window.Show();
        }

        private void editOrder(object sender, RoutedEventArgs e)
        {
            // Edit the currently selected order.
            var order = ordersGrid.SelectedItem as OrderInfo;
            if (order == null)
                return;
            var window = new OrderWindow(order.GetOrder(), _cache, _transaction, null);
            window.Show();
        }

        private void deleteOrder(object sender, RoutedEventArgs e)
        {
            // Delete the currently selected order if it exists.

            var order = ordersGrid.SelectedItem as OrderInfo;
            if (order == null)
                return;
            using (_transaction.Scope())
            {
                // Make this change in the transaction scope.
                Customer.Orders.Remove(order.GetOrder());
            }
        }
    }
}
