using log4net;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using TSManagementApp.Models;
using TSManagementApp.Properties;
using TSManagementApp.Utils;
using TSManagementApp.Views;
using OpenFileDialog = System.Windows.Forms.OpenFileDialog;

namespace TSManagementApp.ViewModels
{
    public class NecoException : Exception
    {
        public NecoException()
        {
        }

        public NecoException(string message) : base(message)
        {
        }

        public NecoException(string message, Exception innerException) : base(message, innerException)
        {
        }
    }

    public class MainWindowViewModel : BaseViewModel
    {
        #region Logger
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion

        private MainWindowView _mainWinView;
        public MainWindowViewModel(MainWindowView mainWinView)
        {
            Manager.Instance.GetInstance();
            _mainWinView = mainWinView;
            InitCommands();
            ToolbarPanelIsVisible = true;
            StatePanelIsVisible = true;
            ListPanelIsVisible = true;
            TimeStamps = Manager.Instance.TimeStampsManager.TimeStamps;
            GoUcAbout();
            
        }

        #region Properties

        private UserControl _currentUserControl;
        public UserControl CurrentUserControl { get => _currentUserControl; set { _currentUserControl = value; OnPropertyChanged("CurrentUserControl"); } }
       
        public ObservableCollection<TimeStampReqRes> TimeStamps { get; set; }
        private TimeStampReqRes _selectedTimeStamp;
        public TimeStampReqRes SelectedTimeStamp
        {
            get => _selectedTimeStamp;
            set
            {
                if (_selectedTimeStamp != value)
                {
                    _selectedTimeStamp = value;
                    TimeStampDetailsView timeStampDetails = new TimeStampDetailsView(this, _selectedTimeStamp, _mainWinView);
                    CurrentUserControl = timeStampDetails;
                    OnPropertyChanged("SelectedTimeStamp");
                }
            }
        }

        private bool _toolbarPanelIsVisible;
        public bool ToolbarPanelIsVisible { get => _toolbarPanelIsVisible; set { _toolbarPanelIsVisible = value; OnPropertyChanged("ToolbarPanelIsVisible"); } }
        private bool _statePanelIsVisible;
        public bool StatePanelIsVisible { get => _statePanelIsVisible; set { _statePanelIsVisible = value; OnPropertyChanged("StatePanelIsVisible"); } }
        private bool _listPanelIsVisible;
        public bool ListPanelIsVisible { get => _listPanelIsVisible; set { _listPanelIsVisible = value; OnPropertyChanged("ListPanelIsVisible"); } }
        private bool _newUpdateIsAvailable;
        public bool NewUpdateIsAvailable { get => _newUpdateIsAvailable; set { _newUpdateIsAvailable = value; OnPropertyChanged("NewUpdateIsAvailable"); } }
        

        // UserControls
        private UserControl _ucAbout;
        private UserControl _ucSettings;
        private UserControl _ucTimeStampDetails;


        public void GoUcAbout()
        {
            if (_ucAbout == null)
                _ucAbout = new AboutView();
            CurrentUserControl = _ucAbout;
        }

        public void GoUcSettings()
        {
            _ucSettings = new SettingsView(this);
            CurrentUserControl = _ucSettings;
        }

        public void GoUcTimeStampDetails()
        {
            _ucTimeStampDetails = new TimeStampDetailsView(this, SelectedTimeStamp, _mainWinView);
            CurrentUserControl = _ucTimeStampDetails;
        }

        #endregion

        #region Commands

        public ICommand CommandGoUcAbout { get; set; }
        public ICommand CommandGoUcSettings { get; set; }
        public ICommand CommandCreateNewTimestamp { get; set; }
        public ICommand CommandOpenExistingTimeStamp { get; set; }
        public ICommand CommandVerifyTimeStamp { get; set; }
        public ICommand CommandDeleteTimeStampFromList { get; set; }
        public ICommand CommandPrintCurrentUserControl { get; set; }
        public ICommand CommandExitApp { get; set; }
        public ICommand CommandPrinPreviewCurrentUserControl { get; set; }

        public void CreateNewTimeStamp()
        {
            var path = GetFilePathFromOpenFileDialog(Resources.CreateTsVM_ChooseFile, 
                $"{Resources.CreateTsVM_PdfFile}|*.pdf|{Resources.CreateTsVM_Textfiles}|*.txt;*.docx;*.doc;*.rtf|{Resources.CreateTsVM_Allfiles}|*.*");
            if (!string.IsNullOrWhiteSpace(path))
            {
                CreateTimeStampView createTimeStamp = new CreateTimeStampView(_mainWinView, this, path);
                createTimeStamp.ShowDialog();
            }
        }

        public void OpenExistingTimeStamp()
        {
            try
            {
                using (OpenFileDialog dialog = new OpenFileDialog())
                {
                    string filePath = GetFilePathFromOpenFileDialog(Resources.MainWindowVM_PickTsFile,
                        $"{Resources.MainWindowVM_QualifiedTs}|*.tsr;*.tst|{Resources.CreateTsVM_Allfiles}|*.*");
                    if (!string.IsNullOrWhiteSpace(filePath))
                    {
                        FileInfo tsFileInfo = new FileInfo(filePath);
                        VerifyTimeStampView verify2 = new VerifyTimeStampView(_mainWinView, tsFileInfo.FullName);
                        verify2.ShowDialog();
                        SelectedTimeStamp = TimeStamps.Last();
                        GoUcTimeStampDetails();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error($"Error while opening existing time stamp - {ex.ToString()}");
                Messages.MsgError($"{Resources.MainWindowVM_ErrorWhileOpeningExistingTs} - {ex.Message}");
            }
        }

        public void VerifyTimeStamp()
        {
            
            try
            {
                VerifyTimeStampView verifyTimeStamp = new VerifyTimeStampView(_mainWinView);
                verifyTimeStamp.ShowDialog();
            }
            catch (Exception ex)
            {
                log.Error($"Error while verifying existing time stamp - {ex.ToString()}");
                Messages.MsgError($"{Resources.MainWindowVM_ErrorwhileVerifyingExistingTs} - {ex.Message}");
            }
        }

        public void DeleteTimeStampFromList()
        {
            try
            {
                if (SelectedTimeStamp != null)
                {
                    Manager.Instance.TimeStampsManager.DeleteOneTimeStamp(SelectedTimeStamp);
                    GoUcAbout();
                }
            }
            catch (Exception ex)
            {
                log.Error($"Error while deleting selected time stamp from list - {ex.ToString()}");
                throw;
            }
        }

        public void PrintCurrentUserControl()
        {
            try
            {
                PrintDialog dialog = new PrintDialog();
                dialog.PrintVisual(_mainWinView, Resources.MainWindowVM_PrintCurrentWindow);
            }
            catch (Exception ex)
            {
                log.Error($"Error while printing application screenshot - {ex.ToString()}");
            }
        }

        public void PrintPreviewCurrentUserControl()
        {
            try
            {
                Window win = _mainWinView;
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)win.ActualWidth, (int)win.ActualHeight, 96, 96, PixelFormats.Pbgra32);
                Rect bounds = VisualTreeHelper.GetDescendantBounds(win);
                DrawingVisual dv = new DrawingVisual();
                using (DrawingContext ctx = dv.RenderOpen())
                {
                    VisualBrush vb = new VisualBrush(win);
                    ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
                }
                rtb.Render(dv);
                PngBitmapEncoder png = new PngBitmapEncoder();
                png.Frames.Add(BitmapFrame.Create(rtb));
                using (FileStream stream = new FileStream($"{SystemUtils.UserLocalAppDirectory}\\img.png", FileMode.Create))
                {
                    png.Save(stream);
                }
                string imgTempFilePath = $"{SystemUtils.UserLocalAppDirectory}\\img.png";
                var showImage = new Process();
                showImage.StartInfo.FileName = imgTempFilePath;
                showImage.StartInfo.UseShellExecute = true;
                showImage.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                showImage.StartInfo.CreateNoWindow = true;
                showImage.Start();
            }
            catch (Exception ex)
            {
                log.Error($"Error while creating preview image of selected user control - {ex.ToString()}");
                Messages.MsgError(Resources.MainWindowVM_ErrorWhileCreatingwindowPreview);
            }
        }

        public void ExitApp()
        {
            _mainWinView.Close();
        }
        #endregion

        #region EventsHandlers

        public void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Manager.Instance.SettingsManager.SerializeSettings();
            Manager.Instance.TimeStampsManager.SerializeTimeStamps();

            if (File.Exists($"{SystemUtils.UserLocalAppDirectory}\\img.png"))
                File.Delete($"{SystemUtils.UserLocalAppDirectory}\\img.png");
        }

        #endregion

        #region Methods

        private void InitCommands()
        {
            CommandGoUcAbout = new CommandGeneric(GoUcAbout);
            CommandGoUcSettings = new CommandGeneric(GoUcSettings);
            CommandCreateNewTimestamp = new CommandGeneric(CreateNewTimeStamp);
            CommandVerifyTimeStamp = new CommandGeneric(VerifyTimeStamp);
            CommandOpenExistingTimeStamp = new CommandGeneric(OpenExistingTimeStamp);
            CommandDeleteTimeStampFromList = new CommandGeneric(DeleteTimeStampFromList);
            CommandPrintCurrentUserControl = new CommandGeneric(PrintCurrentUserControl);
            CommandExitApp = new CommandGeneric(ExitApp);
            CommandPrinPreviewCurrentUserControl = new CommandGeneric(PrintPreviewCurrentUserControl);
        }

        private string GetFilePathFromOpenFileDialog(string title, string filter)
        {
            try
            {
                using (OpenFileDialog dialog = new OpenFileDialog())
                {
                    dialog.Title = title;
                    dialog.Filter = filter;
                    dialog.Multiselect = false;
                    if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        return dialog.FileName;
                    else
                        return null;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion
    }
}
