using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Threading;
using BeWo.Core;
using BeWo.ServiceProxy;
using BeWo.ViewModel;
using BeWo.ViewModel.ListViewModel;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.Extensions;

using DevExpress.Xpf.Editors;
using DevExpress.Xpf.Grid;
using Microsoft.Win32;

namespace BeWo.View.Detail.Accounting
{
    public partial class InvoiceOverview : BeWoView
    {
        private readonly EquityInvoiceItemEditView _EquityInvoiceItemEditView;

        private readonly GeneralInvoiceItemEditView _GeneralInvoiceItemEditView;

        private readonly SettlementInvoiceItemEditView _SettlementInvoiceItemEditView;

        private readonly SettlementInvoiceItemEditView2 _SettlementInvoiceItemEditView2;

        private readonly ServiceInvoiceItemEditView _ServiceInvoiceItemEditView;

        private InvoiceBaseListVM _Viewmodel;

        private bool mIgnoreCheckChanges = false;

        public InvoiceOverview(InvoiceBaseListVM vm)
        {
            this.InitializeComponent();
            this.ViewModel = vm;
            this.DownloadLinkEngine = new DownloadLinkEngine();
            this.linkExcelExport.NavigateUri = this.DownloadLinkEngine.GenerateNewExcelLink();

            this.gridView.ShownEditor += this.gridView_ShownEditor;
            this.gridView.HiddenEditor += new EditorEventHandler(gridView_HiddenEditor);
            this._EquityInvoiceItemEditView = new EquityInvoiceItemEditView();
            this._GeneralInvoiceItemEditView = new GeneralInvoiceItemEditView();
            this._SettlementInvoiceItemEditView = new SettlementInvoiceItemEditView();
            this._SettlementInvoiceItemEditView2 = new SettlementInvoiceItemEditView2();
            this._ServiceInvoiceItemEditView = new ServiceInvoiceItemEditView();

            this.ViewModel.DateTimeSpanFilter = this.yearMonthFilter.FilterSpan;
	        RefreshInvoiceList();

            this._EquityInvoiceItemEditView.EditingFinished += (s, e) =>
                {
                    this.MainControl.CloseCurrentPopUp();
                    ServiceFacade.DoAccountingServiceAsync(se => se.LoadInvoiceBaseByOid(this._EquityInvoiceItemEditView.ViewModel.DataContract.InvoiceBaseOid.Value), cb => this.RefreshItemInList(cb));
                };

            this._GeneralInvoiceItemEditView.EditingFinished += (s, e) =>
                {
                    this.MainControl.CloseCurrentPopUp();
                    ServiceFacade.DoAccountingServiceAsync(se => se.LoadInvoiceBaseByOid(this._GeneralInvoiceItemEditView.ViewModel.DataContract.InvoiceBaseOid.Value), cb => this.RefreshItemInList(cb));
                };

            this._SettlementInvoiceItemEditView.EditingFinished += (s, e) =>
                {
                    this.MainControl.CloseCurrentPopUp();
                    ServiceFacade.DoAccountingServiceAsync(se => se.LoadInvoiceBaseByOid(this._SettlementInvoiceItemEditView.ViewModel.DataContract.InvoiceBaseOid.Value), cb => this.RefreshItemInList(cb));
                };

            this._SettlementInvoiceItemEditView2.EditingFinished += (s, e) =>
            {
                this.MainControl.CloseCurrentPopUp();
                ServiceFacade.DoAccountingServiceAsync(se => se.LoadInvoiceBaseByOid(this._SettlementInvoiceItemEditView2.ViewModel.DataContract.InvoiceBaseOid.Value), cb => this.RefreshItemInList(cb));
            };

            this._ServiceInvoiceItemEditView.EditingFinished += (s, e) =>
            {
                this.MainControl.CloseCurrentPopUp();
                ServiceFacade.DoAccountingServiceAsync(se => se.LoadInvoiceBaseByOid(this._ServiceInvoiceItemEditView.ViewModel.DataContract.InvoiceBase.InvoiceBaseOid.Value), cb => this.RefreshItemInList(cb));
            };
        }

		private void RefreshInvoiceList()
		{
			DateTime? start = null;
			DateTime? end = null;
			if (ViewModel.DateTimeSpanFilter != null)
			{
				start = ViewModel.DateTimeSpanFilter.StartDate;
				end = ViewModel.DateTimeSpanFilter.EndDate;
			}
			ServiceFacade.DoAccountingServiceAsync(s => s.GetInvoiceBases(start, end), UpdateInvoiceList);
		}

		private void UpdateInvoiceList(IList<InvoiceBaseDC> dcList)
		{
			this.Dispatcher.BeginInvoke(
				DispatcherPriority.Normal,
				(Action)delegate
				{
					ViewModel.UpdateList(dcList);
					this.gridView.BestFitColumns();
				});
			
		}

        public DownloadLinkEngine DownloadLinkEngine { get; set; }

        private InvoiceBaseListVM ViewModel
        {
            get
            {
                return this._Viewmodel;
            }

            set
            {
                this.DataContext = value;
                this._Viewmodel = value;
            }
        }

        private void RefreshItemInList(InvoiceBaseDC cb)
        {
            this.Dispatch(
                delegate
                    {
                        var old = this.ViewModel.VMList.Single(i => i.DataContract.InvoiceBaseOid.Equals(cb.InvoiceBaseOid));
                        var lNew = new InvoiceBaseVM(cb);

                        this.ViewModel.VMList.Remove(old);
                        this.ViewModel.VMList.Add(lNew);
                        this.datagrid_invoices.RefreshData();
                        this.gridView.FocusedRow = lNew;
                    });
        }

        private void SaveIsPaidChange(CheckEdit sender)
        {
            if (!mIgnoreCheckChanges)
            {
                var vm = sender.Tag as InvoiceBaseVM;
                //if (vm.IsPaid != sender.IsChecked.Value)
                //{
                    vm.IsPaid = sender.IsChecked.Value;

                    ServiceFacade.DoAccountingServiceAsync(s => s.SetInvoicePaid(new[] { vm.CommitToDataContract() }.ToList(), vm.IsPaid), cb => vm.DataContract.InvoiceBaseVersion = cb[0], false);
                //}
            }
        }

        private void YearMonthFilter_FilterSpanChanged(object sender, EventArgs<DateTimeSpan> e)
        {
            mIgnoreCheckChanges = true;
            this.ViewModel.DateTimeSpanFilter = e.Data;
			RefreshInvoiceList();
            mIgnoreCheckChanges = false;
        }

        private void btn_delete_Click(object sender, RoutedEventArgs e)
        {
            mIgnoreCheckChanges = true;
            var vm = this.datagrid_invoices.GetCurrentValue<InvoiceBaseVM>();

            if (MessageBox.Show("Sind Sie sicher, dass Sie den gewählten Eintrag löschen möchten?", "Rechnung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
            {
                if (vm.DataContract.Type == InvoiceType.Settlement)
                {
                    this.ViewModel.VMList.Remove(vm);
                    ServiceFacade.DoAccountingServiceAsync(s => s.GetSettlementByInvoiceBaseOid(vm.DataContract.InvoiceBaseOid.Value), cb => ServiceFacade.DoAccountingServiceAsync(s1 => s1.DeactivateSettlementInvoice(new[] { cb }.ToList())));
                }
                else
                {
                    this.ViewModel.VMList.Remove(vm);
                    ServiceFacade.DoAccountingServiceAsync(s => s.DeactivateInvoiceBases(new[] { vm.DataContract }.ToList()));
                }
            }
            mIgnoreCheckChanges = false;
        }

        private void btn_edit_Click(object sender, RoutedEventArgs e)
        {
            var vm = this.datagrid_invoices.GetCurrentValue<InvoiceBaseVM>();

            switch (vm.DataContract.Type)
            {
                case InvoiceType.CustomerEquity:
                    this._EquityInvoiceItemEditView.ViewModel = vm;
                    this.MainControl.ShowControlAsModalPopUp(this._EquityInvoiceItemEditView);
                    break;

                case InvoiceType.General:
                    this._GeneralInvoiceItemEditView.ViewModel = vm;
                    this.MainControl.ShowControlAsModalPopUp(this._GeneralInvoiceItemEditView);
                    break;

                case InvoiceType.Settlement:
                    ServiceFacade.DoAccountingServiceAsync(
                        s => s.GetSettlementByInvoiceBaseOid(vm.DataContract.InvoiceBaseOid.Value), 
                        cb => this.Dispatch(
                            delegate
                                {
                                    if (cb.InvoiceItems == null || cb.InvoiceItems.Count == 0 || cb.DifferentHourlyRateCount > 0)
                                    {
                                        this._SettlementInvoiceItemEditView.ViewModel = new SettlementVM(cb);
                                        this.MainControl.ShowControlAsModalPopUp(this._SettlementInvoiceItemEditView);
                                    } 
                                    else
                                    {
                                        this._SettlementInvoiceItemEditView2.ViewModel = new SettlementVM(cb);
                                        this.MainControl.ShowControlAsModalPopUp(this._SettlementInvoiceItemEditView2);
                                    }
                                }));
                    break;

                case InvoiceType.Service:
                    ServiceFacade.DoAccountingServiceAsync(
                        s => s.GetServiceInvoiceByInvoiceBaseOid(vm.DataContract.InvoiceBaseOid.Value),
                        cb => this.Dispatch(
                            delegate
                            {
                                this._ServiceInvoiceItemEditView.ViewModel = new ServiceInvoiceVM(cb);
                                this.MainControl.ShowControlAsModalPopUp(this._ServiceInvoiceItemEditView);
                            }));
                    break;
            }
        }

        private void checked_changed(object sender, RoutedEventArgs e)
        {
            this.SaveIsPaidChange((CheckEdit)sender);
        }

        private void gridView_Loaded(object sender, RoutedEventArgs e)
        {
            this.gridView.BestFitColumns();
        }

        private void gridView_ShownEditor(object sender, EditorEventArgs e)
        {
            if (e.Editor is CheckEdit)
            {
                var ed = (CheckEdit)e.Editor;
                ed.Tag = e.Row;

                //ed.Unchecked -= this.checked_changed;
                //ed.Unchecked += this.checked_changed;
                //ed.Checked -= this.checked_changed;
                //ed.Checked += this.checked_changed;
            }
        }

        void gridView_HiddenEditor(object sender, EditorEventArgs e)
        {
            if (e.Editor is CheckEdit)
            {
                var ed = (CheckEdit)e.Editor;
                SaveIsPaidChange(ed);
            }   
        }

        private void linkExcelExport_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            var list = ViewModel.VMList;

            var lHeaderCaptions = new List<string>();
            var lContent = new List<List<string>>();

            lHeaderCaptions.Add("Art der Rechnung");
            lHeaderCaptions.Add("Klient/in");
            lHeaderCaptions.Add("Nummer");
            lHeaderCaptions.Add("Datum");
            lHeaderCaptions.Add("Empfänger");
            lHeaderCaptions.Add("Betrag");
            lHeaderCaptions.Add("Notiz");
            lHeaderCaptions.Add("Bezahlt");

            if (list != null)
            {
                lContent.AddRange(list.Select(vm => new List<string>
                                                        {
                                                            vm.TypeString, vm.CustomerName, vm.InvoiceNumber, vm.InvoiceDate.Value.ToShortDateString(), vm.RecipientString, string.Format("{0:0.00}", vm.TotalAmount), vm.Notice, vm.IsPaid ? "Ja" : ""
                                                        }));
            }
			var path = BeWoApp.GetAndCreateUserAppDataPath() + "\\Rechnungen.xls";

            var sf = new SaveFileDialog { FileName = Path.GetFileName(path), Filter = "Microsoft Excel 97-2003-Arbeitsblatt|*.xls|Alle Dateien|*.*" };
            if (sf.ShowDialog() != true)
                return;
            ServiceFacade.DoDownloadServiceSync(s => BeWoUtils.WriteExcelFile(s.PrepareExcelFile(DownloadLinkEngine.ExcelFileId, lHeaderCaptions, lContent), sf.FileName));
        }

        private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
        {
			BeWoUtils.NavigateToReportUri(((Hyperlink)sender).NavigateUri.ToString(), "Druckvorschau");
        }

		private void ReloadButton_OnClick(object sender, RoutedEventArgs e)
		{
			RefreshInvoiceList();
		}
    }

}