using BeWo.ServiceProxy;
using BeWo.View;
using BeWo.ViewModel;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Threading;

namespace BeWo.Core
{
    public class DocumentWatcher
    {

        private FileSystemWatcher watcher;

        private List<DocumentWatcherInfo> ueberwachteDateien = new List<DocumentWatcherInfo>();

        private Dictionary<String, bool> offeneDialoge = new Dictionary<String, bool>();

        private int x = 1;

        private UploadPackage lUlPackage;

        public delegate void FileCreatedDelegate(long? folderOid, long? objectOid, TableID objectTid, FileAttachmentDC fileAttachment);

        public delegate void FileDeletedDelegate(long? folderOid, long? objectOid, TableID objectTid, long fileAttachmentOid);

        public event FileCreatedDelegate FileCreated;

        public event FileDeletedDelegate FileDeleted;

        public void StoppeDateiUeberwachung(String fileName)
        {
            var dwi = GetDocumentWatcherInfo(fileName);

            if (dwi != null)
            {
                ueberwachteDateien.Remove(dwi);
            }
        }

        public void StarteDateiUeberwachung(DocumentWatcherInfo dwi)
        {
            try
            {
                if (!WirdDateiUeberwacht(dwi.FileName))
                {
                    ueberwachteDateien.Add(dwi);
                }
                if (watcher == null)
                {
                    FileInfo fi = new FileInfo(dwi.FileName);
                    watcher = new FileSystemWatcher(fi.DirectoryName);

                    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                       | NotifyFilters.FileName | NotifyFilters.DirectoryName;

                    watcher.EnableRaisingEvents = true;
                    watcher.Changed += new FileSystemEventHandler(OnChanged);
                   
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Fehler: " + e.StackTrace);
            }

        }

        private void OnChanged(object source, FileSystemEventArgs e)
        {
            if (WirdDateiUeberwacht(e.FullPath))
            {
                BeWoApp.CurrentBeWo.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate
                {
                    if (!offeneDialoge.ContainsKey(e.FullPath))
                    {
                        var dialog = new UploadDialog(e.FullPath, x);
                       
                        offeneDialoge.Add(e.FullPath, true);
                       
                        dialog.ShowDialog();

                        if (dialog.Upload)
                        {
                            bool wert = true;
                            while (wert)
                            {
                                wert = UpdateDocument(e.FullPath);
                            }
                            dialog.Upload = false;          
                        }
                        offeneDialoge.Remove(e.FullPath);
                    }
                });
            }

            Console.WriteLine("Datei " + e.FullPath + " hat sich geändert. Veränderungstyp: " + e.ChangeType);
        }

        private bool WirdDateiUeberwacht(string fileName)
        {
            foreach (var dwi in ueberwachteDateien)
            {
                if (dwi.FileName == fileName)
                {
                    return true;
                }
            }
            return false;
        }

        private DocumentWatcherInfo GetDocumentWatcherInfo(string fileName)
        {
            foreach (var dwi in ueberwachteDateien)
            {
                if (dwi.FileName == fileName)
                {
                    return dwi;
                }
            }
            return null;
        }

        public bool UpdateDocument(String file)
        {
            var dwi = GetDocumentWatcherInfo(file);
          
            if (dwi != null)
            {
                try
                {
                    var upload = new ProgressStream(File.OpenRead(file));

                    lUlPackage = new UploadPackage(dwi.BeWoFolderOid, 0, dwi.FileName, dwi.FileDescription, (int)dwi.ObjectOid, (int)dwi.ObjectTid, upload);

                    ServiceFacade.DoStreamingServiceAsync(
                        s => s.UploadDocument(lUlPackage),
                        r =>
                        {
                            file = null;

                            upload.Dispose();

                            if (FileCreated != null)
                            {
                                FileCreated(dwi.BeWoFolderOid, dwi.ObjectOid, dwi.ObjectTid, r.Attachment);
                            }
                            ueberwachteDateien.Remove(dwi);
                            LoescheTempDatei(dwi.FileName);
                        },
                                () =>
                                {
                                    upload.Dispose();
                                });
                    DeletOldOneMaybe(dwi);
                }
                catch (Exception ex)
                {
                    int i = 2;
                    var dialog = new UploadDialog(file, i);
                    dialog.ShowDialog();
                    if (dialog.erneutversuchen == true)
                    {
                        dialog.erneutversuchen = false;
                        return true;
                    }
                    else
                    {
                        dialog.erneutversuchen = false;
                        return false;
                    }
                }
            } return false;
        }

        private void DeletOldOneMaybe(DocumentWatcherInfo dwi)
        {
            try
            {
                string file = "Wollen sie das alte Dokument Behalten ?";
                int i = 3;

                var dialog = new UploadDialog(file, i);
                dialog.ShowDialog();
                if (dialog.Upload)
                {
                    DeletOldDatai(dwi);

                    if (FileDeleted != null && dwi.FileAttachmentOid.HasValue)
                    {
                        FileDeleted(dwi.BeWoFolderOid, dwi.ObjectOid, dwi.ObjectTid, dwi.FileAttachmentOid.Value);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine();
            }
        }

        private void DeletOldDatai(DocumentWatcherInfo dwi)
        {
            try
            {
                if (dwi.FileAttachmentOid.HasValue)
                {
                    if (System.Windows.MessageBox.Show("ACHTUNG: Das Löschen von Dateien kann nicht rückgängig gemacht werden!\nWollen Sie das Dokument '" + dwi.FileName + "' wirklich löschen?", "Löschen bestätigen", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                    {
                        return;
                    }
                    ServiceFacade.DoOperationsServiceAsync(s => s.DeleteFileAttachment(dwi.FileAttachmentOid.Value, dwi.FileAttachmentVersion.Value));
                }
            }
            catch (Exception e)
            {
                System.Windows.MessageBox.Show(e.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
        }


        internal void LoescheAlleTempDateien()
        {
            foreach (var file in ueberwachteDateien)
            {
                LoescheTempDatei(file.FileName);
            }
        }


        internal void LoescheTempDateien()
        {
            foreach (var file in ueberwachteDateien)
            {
                LoescheTempDatei(file.FileName);
            }
        }

        internal void LoescheTempDatei(String fileName)
        {

            try
            {
                File.Delete(fileName);
            }
            catch (Exception)
            {
                //ignorieren
            }
        }

    }

    public class DocumentWatcherInfo
    {
        public String FileName { get; set; }

        public String FileDescription { get; set; }

        public long? BeWoFolderOid { get; set; }

        public long? FileAttachmentOid { get; set; }

        public long? FileAttachmentVersion { get; set; }

        public long? ObjectOid { get; set; }
        
        public TableID ObjectTid { get; set; }

        public DocumentWatcherInfo(String filename, String fileDescription, long? bewoFolderOid, long? fileAttschmentOid, long? fileAttachmentVersion, long? objectOid, TableID objectTid)
        {
            this.FileName = filename;
            this.FileDescription = fileDescription;
            this.BeWoFolderOid = bewoFolderOid;
            this.FileAttachmentOid = fileAttschmentOid;
            this.FileAttachmentVersion = fileAttachmentVersion;
            this.ObjectOid = objectOid;
            this.ObjectTid = objectTid;
        }

    }
}
