using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Threading;

using BeWo.Core;
using BeWo.ServiceProxy;
using BeWo.Validation;
using BeWo.ViewModel;

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Services;
using BS.Shared.Core;

using Microsoft.Win32;

namespace BeWo.View.Detail
{
    public partial class AccountingTransactionBookingView
    {
        public static Visibility InsertedOnAndByVisibility
        {
            get
            {
                return BeWoApp.AppSettings.HideServiceRecordInsertedByAndInsertedOn ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        private List<FlatSupportConceptTreeNodeDC> _FlatSupportConceptItems;

        private AccountingBookingVM _ViewModel;

        public List<FlatSupportConceptTreeNodeDC> FlatSupportConceptItems
        {
            get { return _FlatSupportConceptItems; }
            set { _FlatSupportConceptItems = value; }
        }

        public AccountingTransactionBookingView(AccountingBookingVM pViewModel)
        {
            InitializeComponent();
            popup_content.Visibility = Visibility.Hidden;
            ViewModel = pViewModel;

            DownloadLinkEngine = new DownloadLinkEngine();
            linkExcelExport.NavigateUri = DownloadLinkEngine.GenerateNewExcelLink();

            Loaded += AccountingTransactionBookingView_Loaded;
        }

        public override bool CanDelete
        {
            get
            {
                return false;
            }
        }

        public DownloadLinkEngine DownloadLinkEngine { get; set; }

        public override string Title
        {
            get
            {
                return "Finanzbuchung";
            }
        }

        public bool WithoutClient
        {
            get
            {
                return ViewModel != null && ViewModel.WithoutClient;
            }

            set
            {
                if (ViewModel != null)
                {
                    ViewModel.WithoutClient = value;
                }
            }
        }

        internal override DependencyObject ValidationOnSaveRootElement
        {
            get
            {
                return accountingTransactionGrid;
            }
        }

        internal AccountingBookingVM ViewModel
        {
            get
            {
                return _ViewModel;
            }

            set
            {
                DataContext = value;

                _FlatSupportConceptItems = CreateFlatSupportConceptItems(value.SupportConceptTree);
                supportConceptSelectionControl.SelectedItem = _FlatSupportConceptItems[0];

                _ViewModel = value;

                combobox_categories.ItemsSource = value.Categories;

                _ViewModel.AccountingTransactionListChanged += ViewModel_AccountingTransactionListChanged;

                if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.AccountingTransactionView_Create) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.CreateAll))
                {
                    newObjectInfoGrid.IsEnabled = false;
                    button_add.IsEnabled = false;
                }
            }
        }

        public void AnimateOpacity(double pOpacitiy, double pDuration)
        {
            var lAnimation = new DoubleAnimation {From = rootGrid.Opacity, To = pOpacitiy, Duration = TimeSpan.FromMilliseconds(pDuration)};

            rootGrid.BeginAnimation(OpacityProperty, lAnimation);
        }

        public override void Delete()
        {
            var vm = GetSelectedAccountingTransactionVM();

            if (vm != null)
            {
                if (MessageBox.Show("Sind Sie sicher, dass Sie den gewählten Eintrag löschen möchten?", "Buchung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                {
                    var test = ViewModel.AccountingTransactionVMList.Remove(vm);

                    var lDC = vm.CommitToDataContract();
                    ServiceFacade.DoOperationsServiceAsync(s => s.DeleteAccountingTransaction(lDC.AccountingTransactionOid.Value, lDC.AccountingTransactionVersion.Value), RefreshGrid);
                }
            }
        }

        public AccountingTransactionVM GetSelectedAccountingTransactionVM()
        {
            return (AccountingTransactionVM) accountingTransactionGrid.SelectedItem;
        }

        public void SelectCostBearer2SupportConcept(long costBearer2SupportConceptOid)
        {
            var items = _FlatSupportConceptItems;

            if (items != null)
            {
                FlatSupportConceptTreeNodeDC found = null;

                foreach (var i in items)
                {
                    if (found == null)
                    {
                        var item = i;
                        if (item != null && item.SupportConceptTreeNodeDC != null)
                        {
                            if (item.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC != null && item.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer2SupportConceptOid == costBearer2SupportConceptOid)
                            {
                                found = item;
                            }
                        }
                    }
                }

                if (found != null)
                {
                    supportConceptSelectionControl.SelectedItem = found;
                }
            }
        }

        public void SetSelectedAccountingTransactionVM(AccountingTransactionVM vm)
        {
            accountingTransactionGrid.SelectedItem = vm;
        }

        protected override void Save()
        {
            var lToDos = new List<Action<IOperationsService>>();

            if (ViewModel.AddedCount > 0)
            {
                lToDos.Add(
                    s =>
                    {
                        var oids = s.InsertNewAccountingTransactions(ViewModel.CommitAdded());
                        var idx = 0;

                        foreach (var vm in ViewModel.AccountingTransactionVMList.Where(vm => vm.IsNew))
                        {
                            vm.IsNew = false;
                            vm.DataContract.AccountingTransactionVersion = 1;
                            vm.DataContract.AccountingTransactionOid = oids[idx++];
                        }
                    });
            }

            ServiceFacade.DoMultipleOperationsServicesAsync(lToDos, ReloadViewModel);
        }

        private void AccountingTransactionBookingView_Loaded(object sender, RoutedEventArgs e)
        {
            supportConceptSelectionControl.Focus();
        }

        private void AccountingTransactionGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (!IsPartOf(e.OriginalSource, typeof(ScrollBar)))
            {
                Edit();
            }
        }
        
        private void CloseEditView()
        {
            SetPopupViewVisible(false);
            popup_content.Child = null;
        }

        private List<FlatSupportConceptTreeNodeDC> CreateFlatSupportConceptItems(IEnumerable<SupportConceptTreeNodeDC> list)
        {
            _FlatSupportConceptItems = new List<FlatSupportConceptTreeNodeDC> {new FlatSupportConceptTreeNodeDC()};

            foreach (var dc in list)
            {
                CreateFlatSupportConceptItemsForNode(dc);
            }

            return _FlatSupportConceptItems;
        }

        private void CreateFlatSupportConceptItemsForNode(SupportConceptTreeNodeDC node)
        {
            if (node.ChildNodes == null || node.ChildNodes.Count == 0)
            {
                if (node.Customer != null && node.SupportConcept != null && node.SupportConceptCostBearerRelDC != null)
                {
                    if (node.SupportConcept.ActivationType == ActivationTypeId.Active)
                    {
                        var flatNode = new FlatSupportConceptTreeNodeDC {SupportConceptTreeNodeDC = node};

                        _FlatSupportConceptItems.Add(flatNode);
                    }
                }
            }
            else
            {
                foreach (var dc in node.ChildNodes)
                {
                    CreateFlatSupportConceptItemsForNode(dc);
                }
            }
        }

        private void Edit()
        {
            var vm = GetSelectedAccountingTransactionVM();
            if (vm != null && vm.EditAllowed)
            {
                var editView = new AccountingTransactionEditView();
                popup_content.Child = editView;
                popup_content.Width = 550;
                double height = 350;

                if (rootGrid.ActualHeight < height)
                {
                    height = rootGrid.ActualHeight;
                }

                popup_content.Height = height;

                if (editView.CommandBindings.Count == 0)
                {
                    editView.CommandBindings.Add(
                        new CommandBinding(
                            ApplicationCommands.Close,
                            (s, e) =>
                            {
                                if (editView.DoSaveCheck())
                                {
                                    CloseEditView();
                                    ViewModel.RefreshAccountingTransactionsForSelectedTreeNode();

                                    SetSelectedAccountingTransactionVM(vm);
                                }
                            }));
                    editView.CommandBindings.Add(
                        new CommandBinding(
                            ApplicationCommands.Save,
                            (s, e) =>
                            {
                                if (editView.IsValid() && editView.IsCustomerChangeAllowed())
                                {
                                    editView.SaveData();
                                    CloseEditView();
                                    ViewModel.RefreshAccountingTransactionsForSelectedTreeNode();

                                    SetSelectedAccountingTransactionVM(vm);
                                }
                            }));
                }

                editView.InitView(ViewModel, vm, _FlatSupportConceptItems, WithoutClient);
                editView.ParentView = this;
                SetPopupViewVisible(true);
            }
        }

        private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
        {
            for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                var child = VisualTreeHelper.GetChild(obj, i);
                if (child is childItem)
                {
                    return (childItem)child;
                }

                var childOfChild = FindVisualChild<childItem>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }

            return null;
        }

        private static bool IsPartOf(object p, Type type)
        {
            if (p != null)
            {
                var fe = p as FrameworkElement;
                if (fe != null)
                {
                    if (fe.GetType() == type)
                    {
                        return true;
                    }

                    return IsPartOf(fe.TemplatedParent, type);
                }
            }

            return false;
        }

        private void RefreshGrid()
        {
            Dispatcher.BeginInvoke(
                DispatcherPriority.Normal,
                (Action) delegate
                {
                    var selected = GetSelectedAccountingTransactionVM();
                    ViewModel.RefreshAccountingTransactionsForSelectedTreeNode();
                    SetSelectedAccountingTransactionVM(selected);
                });
        }

        private void ReloadViewModel()
        {
            ViewModel.PrototypeVM.Amount = null;
            ViewModel.PrototypeVM.Notice = string.Empty;
        }

        private void SelectedItemChanged(FlatSupportConceptTreeNodeDC selectedNode)
        {
            if (ViewModel != null)
            {
                ViewModel.ChangeTreeItemSelection(selectedNode);
                accountingTransactionGrid.SelectedIndex = -1;

                var sv = FindVisualChild<ScrollViewer>(accountingTransactionGrid);
                sv.ScrollToTop();
            }
        }

        private void SetPopupViewVisible(bool visible)
        {
            popup_content.Visibility = visible ? Visibility.Visible : Visibility.Hidden;

            if (visible)
            {
                AnimateOpacity(0.5, 200);
            }
            else
            {
                AnimateOpacity(1, 100);
            }
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            var vm = ((TextBox) sender).Tag as AccountingTransactionVM;
            if (vm != null)
            {
                accountingTransactionGrid.SelectedItem = vm;
            }
        }


        private void ViewModel_AccountingTransactionListChanged(object sender, EventArgs e)
        {
            accountingTransactionGrid.ItemsSource = _ViewModel.AccountingTransactionsForSelectedSupportConcept.OrderByDescending(vm => vm.BookingDate).ToList();
        }

        private void btnDelete_Click(object sender, RoutedEventArgs e)
        {
            var vm = ((Button) sender).Tag as AccountingTransactionVM;
            if (vm != null)
            {
                accountingTransactionGrid.SelectedItem = vm;
            }

            Delete();
        }

        private void btnEdit_Click(object sender, RoutedEventArgs e)
        {
            var vm = ((Button) sender).Tag as AccountingTransactionVM;
            if (vm != null)
            {
                accountingTransactionGrid.SelectedItem = vm;
            }

            Edit();
        }

        private void button_add_Click(object sender, RoutedEventArgs e)
        {
            var lValid = ValidationTrigger.Validate(rootGrid);

            if (lValid)
            {
                var atvm = ViewModel.CreateFromPrototype();

                ViewModel.AccountingTransactionVMList.Add(atvm);

                Save();
                ViewModel.RefreshAccountingTransactionsForSelectedTreeNode();
            }
        }

        private void chkWithClient_Checked(object sender, RoutedEventArgs e)
        {
            if (customerInfoGrid != null)
            {
                customerInfoGrid.Visibility = Visibility.Visible;
            }


            WithoutClient = false;

            if (supportConceptSelectionControl != null)
            {
                var selectedNode = supportConceptSelectionControl.SelectedItem;
                SelectedItemChanged(selectedNode);
            }

            if (txtMonthlyAmount != null)
            {
                txtMonthlyAmount.Visibility = Visibility.Visible;
            }

            if (txtOpenAmount != null)
            {
                txtOpenAmount.Visibility = Visibility.Visible;
            }
        }

        private void chkWithClient_Unchecked(object sender, RoutedEventArgs e)
        {
            if (customerInfoGrid != null)
            {
                customerInfoGrid.Visibility = Visibility.Collapsed;
            }


            if (txtMonthlyAmount != null)
            {
                txtMonthlyAmount.Visibility = Visibility.Collapsed;
            }

            if (txtOpenAmount != null)
            {
                txtOpenAmount.Visibility = Visibility.Collapsed;
            }

            WithoutClient = true;

            SelectedItemChanged(null);
        }

        private void supportConceptSelectionControl_ItemSelected(object sender, EventArgs<FlatSupportConceptTreeNodeDC> e)
        {
            var selectedNode = e.Data;
            SelectedItemChanged(selectedNode);
        }

        private void linkExcelExport_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            var list = accountingTransactionGrid.ItemsSource as List<AccountingTransactionVM>;

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

            lHeaderCaptions.Add("Buchungsdatum");
			lHeaderCaptions.Add("Gültigkeitsdatum");
			lHeaderCaptions.Add("Betrag");
            lHeaderCaptions.Add("Kategorie");
            lHeaderCaptions.Add("Klient");
            lHeaderCaptions.Add("Hilfeplan");
            lHeaderCaptions.Add("Kostenträger");
            lHeaderCaptions.Add("Kommentar");

            if (list != null)
            {
                foreach (var vm in list)
                {
	                var content = new List<string>();

					content.Add(String.Format("{0:d}", vm.BookingDate));
					content.Add(String.Format("{0:d}", vm.ValidityDate));

					content.Add(String.Format("{0:0.00}", vm.Amount));
					

                    var relDC                              = vm.CostBearerRel;
                    CompactCustomerDC customer             = null;
                    CompactSupportConceptDC supportConcept = null;
                    CompactOrganisationDC costBearer       = null;

                    content.Add(vm.Category != null ? vm.Category.ToString() : string.Empty);

                    if (relDC != null)
                    {
                        supportConcept = relDC.SupportConcept;
                        costBearer = relDC.CostBearer;
                        if (supportConcept != null)
                        {
                            customer = supportConcept.Customer;
                        }
                    }

                    content.Add(customer != null ? customer.ToString() : string.Empty);

                    content.Add(supportConcept != null ? supportConcept.ToString() : string.Empty);

                    content.Add(costBearer != null ? costBearer.ToString() : string.Empty);

                    content.Add(vm.Notice);

                    lContent.Add(content);
                }
            }

			var path = BeWoApp.GetAndCreateUserAppDataPath() + "\\Abschlagszahlungen.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 linkMonthlyAmount_Click(object sender, RoutedEventArgs e)
        {
            var selectedNode = supportConceptSelectionControl.SelectedItem;
            if (selectedNode != null && selectedNode.SupportConceptTreeNodeDC != null)
            {
                var relDC  = selectedNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC;
                var calc   = Calculations.GetInstance(relDC.CostBearer.CostBearerID);
                var amount = calc.GetApprovedAmountPerMonth(relDC, DateTime.Now) ?? 0m;

                ViewModel.PrototypeVM.Amount = Math.Round(amount, 2, MidpointRounding.AwayFromZero);
            }
        }

        private void linkOpenAmount_Click(object sender, RoutedEventArgs e)
        {
            var selectedNode = supportConceptSelectionControl.SelectedItem;
            if (selectedNode != null && selectedNode.SupportConceptTreeNodeDC != null)
            {
                var amount = ViewModel.OpenAmount;
                ViewModel.PrototypeVM.Amount = Math.Round(amount, 2, MidpointRounding.AwayFromZero);
            }
        }
    }
}