using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;

using BeWo.Annotations;
using BeWo.Core;
using BeWo.Office;
using BeWo.Office.TableModels;
using BeWo.ServiceProxy;
using BeWo.View.Navigation.Filter;

namespace BeWo.View.Detail
{
    public partial class MailMergeWindow : INotifyPropertyChanged
    {
        internal CustomFilter _CustomFilter;
        private bool _AutomatedUncheck;
        public string TemplateTypeString { get; set; }
        public BeWoView ParentView { get; set; }
        private readonly List<IFilterableDC> _AllObjects;
        public IEnumerable<IFilterableDC> AllObjects { get { return _AllObjects; } }
        private readonly FileAttachmentType fileType = FileAttachmentType.NotSpecified;

        private AbstractSorter mSorter;
        public AbstractSorter Sorter
        {
            get
            {
                return mSorter;
            }

            set
            {
                mSorter = value;
                SortCombo.Items.Clear();

                if (mSorter == null) return;

                SortPanel.Visibility = mSorter.SortItems.Count > 0 ? Visibility.Visible : Visibility.Collapsed;

                foreach (var item in mSorter.SortItems)
                    SortCombo.Items.Add(item);

                SortCombo.SelectedIndex = 0;
            }
        }

        private List<FileAttachmentDC> _WordTemplates;
        public List<FileAttachmentDC> WordTemplates 
        { 
            get { return _WordTemplates; }
            set
            {
                _WordTemplates = value;
                OnPropertyChanged("WordTemplates");
            } 
        }

        private ObservableCollection<IFilterableDC> _SelectedForPrinting;
        public ObservableCollection<IFilterableDC> SelectedForPrinting
        {
            get { return _SelectedForPrinting; }
            set
            {
                _SelectedForPrinting = value;
                OnPropertyChanged("SelectedForPrinting");
            }
        }

        public CustomFilter CustomFilter
        {
            get
            {
                return _CustomFilter;
            }

            set
            {
                _CustomFilter = value;
                OnPropertyChanged("CustomFilter");
            }
        }

        public IEnumerable<IFilterableDC> AllListObjects
        {
            get
            {
                return ObjectListBox.Items.Cast<IFilterableDC>().ToList();
            }
        }

        public MailMergeWindow(BeWoView parentView, Type templateType, List<IFilterableDC> allObjects, IFilterableDC selectedObject)
        {
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, (s, e) => Close()));

            _SelectedForPrinting = new ObservableCollection<IFilterableDC>();

            InitializeComponent();
            ParentView = parentView;
            _AllObjects = allObjects;

            Owner = parentView == null ? BeWoApp.CurrentBeWo.MainWindow : GetWindow(parentView);

            if (BeWoApp.MainControl.ModalPopUpBackGround == null)
                BeWoApp.MainControl.ShowModalBackground();

            DataContext = this;

            if (templateType == typeof (SupportConceptDC))
            {
                TemplateTypeString = "Hilfepläne";
                ObjectListBox.Background = BeWoApp.CurrentBeWo.Resources["SupportConceptListBrush"] as Brush;
                fileType = FileAttachmentType.SupportConceptTemplate;
                ChkShowOnlyMyObjects.Content = "Nur meine Hilfepläne anzeigen";
                ChkShowArchived.Content = "Archivierte Hilfepläne anzeigen";
            }
            else if (templateType == typeof (CustomerDC))
            {
                TemplateTypeString = "Klienten";
                ObjectListBox.Background = BeWoApp.CurrentBeWo.Resources["CustomerContentBrush"] as Brush;
                fileType = FileAttachmentType.CustomerTemplate;
                ChkShowOnlyMyObjects.Content = "Nur meine Klienten anzeigen";
                ChkShowArchived.Content = "Archivierte Klienten anzeigen";
            }
            else if (templateType == typeof(PersonDC))
            {
                ObjectListBox.Background = BeWoApp.CurrentBeWo.Resources["PersonContentBrush"] as Brush;
                fileType = FileAttachmentType.PersonTemplate;
                ChkShowOnlyMyObjects.Visibility = Visibility.Collapsed;
                ChkShowArchived.Content = "Archivierte Personen anzeigen";
            }
            else if (templateType == typeof(OrganisationDC))
            {
                ObjectListBox.Background = BeWoApp.CurrentBeWo.Resources["OrganisationContentBrush"] as Brush;
                fileType = FileAttachmentType.OrganisationTemplate;
                ChkShowOnlyMyObjects.Visibility = Visibility.Collapsed;
                ChkShowArchived.Content = "Archivierte Organisationen anzeigen";
            }

            Closing += delegate { BeWoApp.MainControl.CloseCurrentPopUp(); };

            ServiceFacade.DoOperationsServiceAsync(s => s.GetFileAttachmentInfoByType(fileType), cb => { WordTemplates = cb; });

            ObjectListBox.DataContext = AllObjects.ToObservableSortCollection();

            CreateNewCustomFilter();
        }

        private void CreateNewCustomFilter()
        {
            var filter = new CustomFilter();

            switch (fileType)
            {
                case FileAttachmentType.CustomerTemplate:
                    filter = new CustomerNavigationFilter { ShowOnlyMyCustomers = ChkShowOnlyMyObjects.IsChecked != null && ChkShowOnlyMyObjects.IsChecked.Value };
                    break;
                case FileAttachmentType.SupportConceptTemplate:
                    filter = new SupportConceptNavigationFilter { ShowOnlyMySupportConcepts = ChkShowOnlyMyObjects.IsChecked != null && ChkShowOnlyMyObjects.IsChecked.Value };
                    break;
            }

            CustomFilter = filter;
        }

        private void PrintBtnClick(object sender, RoutedEventArgs e)
        {
            DownloadFileAttachment("Drucken");
        }

        private void PreviewBtnClick(object sender, RoutedEventArgs e)
        {
            DownloadFileAttachment("Vorschau");
        }

        private void DownloadFileAttachment(string action)
        {
            var file = new FileAttachmentDC();
            var fobj = (FileAttachmentDC) VorlagenComboBox.SelectedItem;

            if (!fobj.FileAttachmentOid.HasValue) return;
                
            var fid = fobj.FileAttachmentOid.Value;
            var extension = Path.GetExtension(((FileAttachmentDC) VorlagenComboBox.SelectedItem).FileName);

            if (extension != null && (!extension.Equals(".docx") && !extension.Equals(".doc")))
            {
                MessageBox.Show("Dieses Dateiformat wird leider nicht unterstützt. Bitte benutzen Sie nur .docx oder .doc Dateien.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            ServiceFacade.DoDownloadServiceAsync(f => file = f.GetFileAttachment(fid), cb =>
                {
                    var tmp = Path.GetTempPath() + Path.GetFileName(file.URL);

                    using (var uFileStream = File.Create(tmp))
                    {
                        uFileStream.Write(file.BinaryData, 0, file.BinaryData.Length);
                        uFileStream.Close();

                        switch (action)
                        {
                            case "Drucken":
                                PrintMailMerge(tmp, ViewDestination.Printer);
                                break;
                            case "Vorschau":
                                PrintMailMerge(tmp, ViewDestination.Preview);
                                break;
                        }

                        uFileStream.Dispose();
                    }
                });
        }

        private void PrintMailMerge(string path, ViewDestination viewDestination)
        {
            var wordProcessor = new WordProcessor
                {
                    DocumentPath = path,
                    CreateFormLetter = true
                };

            List<CustomerDC> customers = null;
            List<PersonDC> persons = null;
            List<OrganisationDC> organisations = null;
            List<SupportConceptDC> supportConcepts = null;
            var contractIds = new List<long>();

            if (fileType == FileAttachmentType.CustomerTemplate)
            {
                contractIds.AddRange(SelectedForPrinting.Select(customer => ((CompactCustomerDC)customer).CustomerOid));

                ServiceFacade.DoCustomerServiceSync(cs => customers = cs.GetCustomersById(contractIds));

                if (customers != null)
                    wordProcessor.TableModel = new CustomerTableModel {Customers = customers};
            }
            else if (fileType == FileAttachmentType.PersonTemplate)
            {
                contractIds.AddRange(SelectedForPrinting.Select(person => ((CompactPersonDC)person).PersonOid));

                ServiceFacade.DoCustomerServiceSync(p => persons = p.GetPersonsById(contractIds));

                if (persons != null)
                    wordProcessor.TableModel = new PersonTableModel { Persons = persons };
            }
            else if (fileType == FileAttachmentType.SupportConceptTemplate)
            {
                contractIds.AddRange(SelectedForPrinting.Select(supportConcept => ((CompactSupportConceptDC)supportConcept).SupportConceptOid));

                ServiceFacade.DoCustomerServiceSync(s => supportConcepts = s.GetSupportConceptsById(contractIds));

                if (supportConcepts != null)
                    wordProcessor.TableModel = new SupportConceptTableModel { SupportConcepts = supportConcepts };
            }
            else if (fileType == FileAttachmentType.OrganisationTemplate)
            {
                contractIds.AddRange(SelectedForPrinting.Select(organistation => ((CompactOrganisationDC)organistation).OrganisationOid));

                ServiceFacade.DoCustomerServiceSync(o => organisations = o.GetOrganisationsById(contractIds));

                if (organisations != null)
                    wordProcessor.TableModel = new OrganisationTableModel { Organisations = organisations };
            }

            wordProcessor.CreateReport(viewDestination, null, null);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            if (!e.Cancel && Owner != null) Owner.Focus();
        }

        private void CheckBoxChecked(object checkBox, RoutedEventArgs e)
        {
            var checkedDC = (IFilterableDC) ((CheckBox) checkBox).Tag;
            if(!SelectedForPrinting.Contains(checkedDC))
                SelectedForPrinting.Add(checkedDC);
        }

        private void CheckBoxUnChecked(object checkBox, RoutedEventArgs e)
        {
            var checkedDC = (IFilterableDC)((CheckBox)checkBox).Tag;
            if (SelectedForPrinting.Contains(checkedDC))
                SelectedForPrinting.Remove(checkedDC);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        private void ChkShowOnlyMyObjects_OnClick(object sender, RoutedEventArgs e)
        {
            CreateNewCustomFilter();
            OnPropertyChanged("SelectedForPrinting");
        }

        private void SortDirectionToggleButton_Click(object sender, RoutedEventArgs e)
        {
            SortSearchResult(ObjectListBox.ItemsSource as IEnumerable<IFilterableDC>);
        }

        private void SortCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
                SortSearchResult(e.AddedItems[0] as SortItem, ObjectListBox.ItemsSource as IEnumerable<IFilterableDC>);
        }

        public void SortSearchResult(IEnumerable<IFilterableDC> result)
        {
            if (mSorter == null)
            {
                ObjectListBox.DataContext = result.ToObservableSortCollection();
            }
            else
            {
                var item = SortCombo.SelectedItem as SortItem;
                if (item != null)
                    SortSearchResult(item, result);
            }
        }

        public void SortSearchResult(SortItem item, IEnumerable<IFilterableDC> result)
        {
            if (mSorter == null || item == null) return;
            var items = result;

            if (items == null) return;

            var dir = AbstractSorter.SortDirection.Ascending;

            if (SortDirectionToggleButton.IsChecked != null && SortDirectionToggleButton.IsChecked.Value)
                dir = AbstractSorter.SortDirection.Descending;

            ObjectListBox.DataContext = items.ToObservableSortCollection(mSorter.GetComparison(item, dir));
        }

        private void AlleWaehlenCheckBox_OnChecked(object sender, RoutedEventArgs e)
        {
            SelectedForPrinting.Clear();
            SelectedForPrinting.AddRange(AllListObjects);
            OnPropertyChanged("SelectedForPrinting");
        }

        private void AlleWehlenCheckBox_OnUnchecked(object sender, RoutedEventArgs e)
        {
            if (_AutomatedUncheck)
            {
                _AutomatedUncheck = false;
                return;
            }

            SelectedForPrinting.Clear();
            OnPropertyChanged("SelectedForPrinting");
        }

        private void ChkShowArchived_OnUnchecked(object sender, RoutedEventArgs e)
        {
            _AutomatedUncheck = true;
            AlleWaehlenCheckBox.IsChecked = false;
        }
    }

    public class ListBoxItemStyleSelector : StyleSelector
    {
        public Style SupportConceptStyle { get; set; }
        public Style PersonStyle { get; set; }
        public Style OrganisationStyle { get; set; }
        public Style CustomerStyle { get; set; }

        public override Style SelectStyle(object item, DependencyObject container)
        {
            var itemType = item.GetType();

            if (itemType == typeof (CompactSupportConceptDC))
            {
                return SupportConceptStyle;
            }

            if (itemType == typeof(CompactPersonDC))
            {
                return PersonStyle;
            }

            return itemType == typeof(CompactOrganisationDC) ? OrganisationStyle : CustomerStyle;
        }
    }
}
