using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;


using System.Windows.Data;
using System.Data.Services.Client;
using System.Windows;

namespace DataViewDashboard.ViewModels
{
    public class AsyncOperation
    {
        public DataViewModelBase ViewModel { get; set; }
        public System.Data.Services.Client.DataServiceQuery Query { get; set; }
    }

    public class DataViewModelBase : ViewModelBase
    {
        public DataViewModelBase(DataServiceQuery query)
        {
            this.IsLoading = true;
            query.BeginExecute(OnAsyncExecutionComplete, new AsyncOperation() { Query = query, ViewModel = this });

        }

        private static void OnAsyncExecutionComplete(IAsyncResult result)
        {
            var query = (result.AsyncState as AsyncOperation).Query as DataServiceQuery;
            var viewmodel = (result.AsyncState as AsyncOperation).ViewModel as DataViewModelBase;

            App.Current.Dispatcher.Invoke((Action)delegate
            {
                try
                {
                    var customers = new List<AdventureWorksService.Customer>();
                    var products = new List<AdventureWorksService.Product>();
                    var salesOrderHeaders = new List<AdventureWorksService.SalesOrderHeader>();
                    foreach (var item in query.EndExecute(result))
                    {
                        if (item is AdventureWorksService.Customer)
                        {
                            customers.Add(item as AdventureWorksService.Customer);
                        }
                        else if (item is AdventureWorksService.Product)
                        {
                            products.Add(item as AdventureWorksService.Product);
                        }
                        else if (item is AdventureWorksService.SalesOrderHeader)
                        {
                            salesOrderHeaders.Add(item as AdventureWorksService.SalesOrderHeader);
                        }
                    }
                    if (customers.Count != 0)
                    {
                        viewmodel.Source = new CollectionViewSource() { Source = customers };
                    }
                    else if (products.Count != 0)
                    {
                        viewmodel.Source = new CollectionViewSource() { Source = products };
                    }
                    else if (salesOrderHeaders.Count != 0)
                    {
                        viewmodel.Source = new CollectionViewSource() { Source = salesOrderHeaders };
                    }


                    viewmodel.OnPropertyChanged("Source");
                    viewmodel.OnPropertyChanged("SelectedItem");
                    viewmodel.OnPropertyChanged("SelectedItemIndex");
                    viewmodel.Count = 0; // update count
                    viewmodel.IsLoading = false;
                }
                catch (Exception ex)
                {
                    viewmodel.IsLoading = false;
                    MessageBox.Show("Unable to load data.");
                }

            }, null);

        }

        public CollectionViewSource Source { get; private set; }
        

        private bool isLoading = false;
        public bool IsLoading
        {
            get
            {
                return isLoading;
            }
            set
            {
                isLoading = value;
                OnPropertyChanged("IsLoading");
            }
        }

        private int count = 1;
        public int Count
        {
            get 
            {
                return count;
            }
            set
            {
                count = this.Source.View.Cast<object>().Count();
                OnPropertyChanged("Count");
            }
        }
        
        public int SelectedItemIndex
        {
            get
            {
                if (this.Source != null && this.Source.View != null)
                    return this.Source.View.CurrentPosition;
                else
                    return 0;
            }
        }

        public object SelectedItem
        {
            get
            {
                if (this.Source != null)
                    return this.Source.View.CurrentItem;
                else
                    return null;
            }
        }

        #region NextItemCommand

        // NextItemCommand
        private RelayCommand nextItemCommand;
        public ICommand NextItemCommand
        {
            get
            {
                if (nextItemCommand == null)
                {
                    nextItemCommand = new RelayCommand(param => this.GoToNextItem(), param => this.CanGoForward());
                }
                return nextItemCommand;
            }
        }

        private void GoToNextItem()
        {
            this.Source.View.MoveCurrentToNext();
            OnPropertyChanged("SelectedItem");
        }

        private bool CanGoForward()
        {
            if (this.SelectedItemIndex + 1 < this.Count)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region LastItemCommand

        // LastItemCommand
        private RelayCommand lastItemCommand;
        public ICommand LastItemCommand
        {
            get
            {
                if (lastItemCommand == null)
                {
                    lastItemCommand = new RelayCommand(param => this.GoToLastItem(), param => this.CanGoForward());
                }
                return lastItemCommand;
            }
        }

        private void GoToLastItem()
        {
            this.Source.View.MoveCurrentToLast();
            OnPropertyChanged("SelectedItem");
        }

        #endregion

        #region PreviousItemCommand

        // PreviousItemCommand
        private RelayCommand previousItemCommand;
        public ICommand PreviousItemCommand
        {
            get
            {
                if (previousItemCommand == null)
                {
                    previousItemCommand = new RelayCommand(param => this.GoToPreviousItem(), param => this.CanGoBack());
                }
                return previousItemCommand;
            }
        }

        private void GoToPreviousItem()
        {
            this.Source.View.MoveCurrentToPrevious();
            OnPropertyChanged("SelectedItem");
        }

        #endregion

        #region FirstItemCommand

        // FirstItemCommand
        private RelayCommand firstItemCommand;
        public ICommand FirstItemCommand
        {
            get
            {
                if (firstItemCommand == null)
                {
                    firstItemCommand = new RelayCommand(param => this.GoToFirstItem(), param => this.CanGoBack());
                }
                return firstItemCommand;
            }
        }

        private void GoToFirstItem()
        {
            this.Source.View.MoveCurrentToFirst();
            OnPropertyChanged("SelectedItem");
        }

        private bool CanGoBack()
        {
            if (this.SelectedItemIndex > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region GoToItemCommand

        // GoToItemCommand
        private RelayCommand goToItemCommand;
        public ICommand GoToItemCommand
        {
            get
            {
                if (goToItemCommand == null)
                {
                    goToItemCommand = new RelayCommand(param => this.GoToItem(param));
                }
                return goToItemCommand;
            }
        }

        private void GoToItem(object parameter)
        {
            int i;
            if (int.TryParse(parameter.ToString(), out i))
            {
                if (i > this.Count) i = this.Count;
                this.Source.View.MoveCurrentToPosition(i - 1);
                OnPropertyChanged("SelectedItem");

            }

        }
        #endregion

    }

    public class ViewTypeViewModelBase : ViewModelBase
    {
        public ViewTypeViewModelBase()
        {

        }
    }

    public class DataGridViewTypeViewModel : ViewTypeViewModelBase
    {
        public DataGridViewTypeViewModel()
        {

        }
    }

    public class PropertyGridViewTypeViewModel : ViewTypeViewModelBase
    {
        public PropertyGridViewTypeViewModel()
        {

        }
    }

    public class TileViewTypeViewModel : ViewTypeViewModelBase
    {
        public TileViewTypeViewModel()
        {

        }
    }

    public class CarouselViewTypeViewModel : ViewTypeViewModelBase
    {
        public CarouselViewTypeViewModel()
        {

        }
    }

    public class BookViewTypeViewModel : ViewTypeViewModelBase
    {
        public BookViewTypeViewModel()
        {

        }
    }
}
