using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using pdftron;
using pdftron.PDF;
using pdftron.SDF;
using pdftron.Common;

namespace PDFViewWPFTestCS
{
    /// <summary>
    /// Interaction logic for PDFViewViewer.xaml
    /// </summary>
    public partial class PDFViewViewer : UserControl
    {
        private PDFDoc _pdfdoc = null; // currently open PDF document
        private SideWindowControl _sidecontrol;
        private GridLength _oldwidth = new GridLength(200);
        private PDFViewWPF.Selection _currentSearchSelection;
        private List<Rectangle> _onScreenSelection = new List<Rectangle>();

        private MainWindow Current_Main { get; set; }
        public PDFViewWPF Current_View { get; set; }
        public bool IsNaviOpen { get; set; }
        public double NaviWidth
        {
            get { return DocViewerGrid.ColumnDefinitions[0].Width.Value; }
            set { DocViewerGrid.ColumnDefinitions[0].Width = new GridLength(value); }
        }
        public double ZoomLevel
        {
            get { return Current_View.GetZoom(); }
            set { Current_View.SetZoom(value); }
        }
        public string _safeDocName { get; set; }

        private pdftron.PDF.Tools.ToolManager _ToolManager;
        public pdftron.PDF.Tools.ToolManager ToolManager
        {
            get { return _ToolManager; }
        }

        public PDFViewViewer(MainWindow main_window)
        {
            InitializeComponent();

            PresentationSource source = PresentationSource.FromVisual(Application.Current.MainWindow);

            double scaleFactor = 1;
            if (source != null)
            {
                scaleFactor = 1 / source.CompositionTarget.TransformFromDevice.M11;
            }

            Current_Main = main_window;

            Current_View = new PDFViewWPF();
            Current_View.PixelsPerUnitWidth = scaleFactor;
            Current_View.SetRenderedContentCacheSize(16);
            Current_View.UseLayoutRounding = true;
            _sidecontrol = new SideWindowControl();

            Current_View.SetAntiAliasing(true);
            Current_View.SetPathHinting(true);
            Current_View.SetThinLineAdjustment(true, true);
            Current_View.SetupThumbnails(false, true, true, 500, 200 * 1024 * 1024, 0.2);
            Current_View.SetProgressiveRendering(true);
            Current_View.SetProgressiveRenderingInterval(750);
            Current_View.SetPageBorderVisibility(true);

            NaviBarGrid.Children.Add(_sidecontrol);
            PDFGrid.Children.Add(Current_View);

            _ToolManager = new pdftron.PDF.Tools.ToolManager(Current_View);
            _ToolManager.ToolModeChanged += ToolManager_ToolModeChanged;
            Current_View.Loaded += _pdfviewWpf_Loaded;
            Current_View.OnSetDoc += Current_View_OnSetDoc;

            Current_View.FindTextFinished += Current_View_FindTextFinished;
            Current_View.LayoutChanged += Current_View_LayoutChanged;

            Current_View.CurrentScrollChanged += _pdfviewWpf_ScollChanged; // set zoom textbox value
            Current_View.CurrentZoomChanged += _pdfviewWpf_CurrentZoomChanged; // set zoom textbox value
            Current_View.CurrentPageNumberChanged += Current_View_CurrentPageNumberChanged;
            Current_View.SetDownloadReportHandler(OnDownload, null);

            this.KeyDown += new KeyEventHandler(OnViewKeyDown);
            this.KeyUp += new KeyEventHandler(OnViewKeyUp);

            //hide sidebar
            main_window.btn_collapse.IsEnabled = false;
            main_window.btn_expand.IsEnabled = true;
            PDFGrid.Margin = new Thickness(0);
            SideWindowSplitter.DragCompleted += SideWindowSplitter_DragCompleted;

            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_continuous);
            Current_View.SetPageViewMode(PDFViewWPF.PageViewMode.e_fit_width);
            Current_View.SetBackgroundColor(Colors.DarkGray);
            Current_View.SetUrlExtraction(false);

            // This allows touch interaction
            Current_View.IsManipulationEnabled = true;


            this.ToolManager.SelectedAnnotationsChanged += ToolManager_SelectedAnnotationsChanged;
        }

        private void ToolManager_SelectedAnnotationsChanged()
        {
            List<Annot> annots = ToolManager.SelectedAnnotations;
        }

        /// <summary>
        /// This will be called each time we switch to this tab, and when we first open it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _pdfviewWpf_Loaded(object sender, RoutedEventArgs e)
        {
            Current_Main.txtbox_pagenum.Text = Current_View.GetCurrentPage().ToString();
            Current_Main.SetZoomValue(Current_View.GetZoom());
        }
        
        /// <summary>
        /// This will happen whenever we open a new document.
        /// It is guaranteed to happen after the document is loaded and ready to be used, so we
        /// replicate it here in case there are some timing issues between the loaded handler and he document being loaded.
        /// </summary>
        /// <param name="viewer"></param>
        void Current_View_OnSetDoc(PDFViewWPF viewer)
        {
            Current_Main.txtbox_pagenum.Text = Current_View.GetCurrentPage().ToString();
            Current_Main.slider_zoom.Value = Current_View.GetZoom();
            Current_Main.SetZoomValue(Current_View.GetZoom());
            pdftron.PDF.Action open_action = viewer.GetDoc().GetOpenAction();
            if (open_action.IsValid() && open_action.GetType() == pdftron.PDF.Action.Type.e_JavaScript)
            {
                ActionParameter action_param = new ActionParameter(open_action);
                viewer.ExecuteAction(action_param);
            }
        }

        #region Events

        void ToolManager_ToolModeChanged(pdftron.PDF.Tools.ToolManager.ToolType toolType)
        {
            UpdateToolButtonStates();
        }

        public void UpdateToolButtonStates()
        {
            if (_ToolManager == null)
            {
                return;
            }

            Current_Main.t_pan.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_pan);
            Current_Main.PanToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_pan);

            Current_Main.t_annot_edit.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_annot_edit);
            Current_Main.AnnotationEditToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_annot_edit);

            Current_Main.t_text_rect.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_select_rectangular);

            Current_Main.t_text_struct.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_select);

            Current_Main.LineToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_line_create);
            Current_Main.PolylineToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_polyline_create);
            Current_Main.PolygonToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_polygon_create);
            Current_Main.ArrowToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_arrow_create);
            Current_Main.RectangleToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_rect_create);
            Current_Main.OvalToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_oval_create);
            Current_Main.InkToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_ink_create);
            Current_Main.TextBoxToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_annot_create);
            Current_Main.CalloutToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_callout_create);
            Current_Main.StickyNoteToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_sticky_note_create);
            Current_Main.HighlightToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_highlight);
            Current_Main.UnderlineToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_underline);
            Current_Main.StrikeoutToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_strikeout);
            Current_Main.SquigglyToolMenuItem.IsChecked = (_ToolManager.CurrentTool.ToolMode == pdftron.PDF.Tools.ToolManager.ToolType.e_text_squiggly);
        }


        void Current_View_LayoutChanged(PDFViewWPF viewer)
        {
            UpdatePresentationModeButtonStates();
            HighlightSelection();
        }

        public void UpdatePresentationModeButtonStates()
        {
            Current_Main.SinglePageButton.IsChecked = false;
            Current_Main.SingleContinuousButton.IsChecked = false;
            Current_Main.FacingButton.IsChecked = false;
            Current_Main.FacingContinuousButton.IsChecked = false;
            Current_Main.FacingCoverButton.IsChecked = false;
            Current_Main.FacingCoverContinuousButton.IsChecked = false;

            switch (Current_View.GetPagePresentationMode())
            {
                case PDFViewWPF.PagePresentationMode.e_single_page:
                    Current_Main.SinglePageButton.IsChecked = true;
                    break;
                case PDFViewWPF.PagePresentationMode.e_single_continuous:
                    Current_Main.SingleContinuousButton.IsChecked = true;
                    break;
                case PDFViewWPF.PagePresentationMode.e_facing:
                    Current_Main.FacingButton.IsChecked = true;
                    break;
                case PDFViewWPF.PagePresentationMode.e_facing_continuous:
                    Current_Main.FacingContinuousButton.IsChecked = true;
                    break;
                case PDFViewWPF.PagePresentationMode.e_facing_cover:
                    Current_Main.FacingCoverButton.IsChecked = true;
                    break;
                case PDFViewWPF.PagePresentationMode.e_facing_continuous_cover:
                    Current_Main.FacingCoverContinuousButton.IsChecked = true;
                    break;
            }
        }


        void SideWindowSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            Current_Main.UpdateSidewindowButtons();
        }


        public void SetCurrentPage(int page)
        {
            Current_View.CurrentPageNumber = page;
            //Current_View.SetCurrentPage(page);
        }

        void _pdfviewWpf_CurrentZoomChanged(PDFViewWPF viewer)
        {
            double zoom = Current_View.GetZoom();
            Current_Main.SetZoomValue(zoom);
            HighlightSelection();
        }

        void _pdfviewWpf_ScollChanged(PDFViewWPF viewer, ScrollChangedEventArgs e)
        {
           //add you code here
        }

        void Current_View_CurrentPageNumberChanged(PDFViewWPF viewer, int currentPage, int totalPages)
        {
            Current_Main.txtbox_pagenum.Text = currentPage.ToString();
            HighlightSelection();
        }

        void txtbox_pagenum_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter && !string.IsNullOrWhiteSpace(Current_Main.txtbox_pagenum.Text))
            {
                int pagenum;
                if (Int32.TryParse(Current_Main.txtbox_pagenum.Text, out pagenum))
                    Current_View.SetCurrentPage(pagenum);
            }
        }

        private void txtbox_zoom_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter && !string.IsNullOrWhiteSpace(Current_Main.txtbox_zoom.Text))
            {
                int newzoom;
                if (Int32.TryParse(Current_Main.txtbox_zoom.Text, out newzoom))
                    Current_View.SetZoom(newzoom / 100.0);
            }
        }

        private void OnViewKeyDown(object sender, KeyEventArgs e)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                if (e.Key == Key.F)
                {
                    if (Current_Main.FindTextDialog == null)
                    {
                        Current_Main.FindTextDialog = new FindTextDialog();
                        Current_Main.FindTextDialog.Owner = Current_Main;
                        Current_Main.FindTextDialog.Show();
                    }
                    else
                    {
                        Current_Main.FindTextDialog.ActivateFindText();
                    }
                }
                if (e.Key == Key.S)
                {
                    if (_pdfdoc != null && Current_View != null && (_pdfdoc.IsModified()))
                        this.Save(_pdfdoc.GetFileName());
                }
            }
        }

        void OnViewKeyUp(object sender, KeyEventArgs e)
        {

        }

        public void OpenNavibar()
        {
            DocViewerGrid.ColumnDefinitions[0].Width = new GridLength(200);

            Current_Main.btn_expand.IsEnabled = false;
            Current_Main.btn_collapse.IsEnabled = true;
            IsNaviOpen = true;
        }

        public void CloseNavibar()
        {
            _oldwidth = DocViewerGrid.ColumnDefinitions[0].Width;
            DocViewerGrid.ColumnDefinitions[0].Width = new GridLength(0);

            Current_Main.btn_collapse.IsEnabled = false;
            Current_Main.btn_expand.IsEnabled = true;
            IsNaviOpen = false;
        }

        #endregion

        #region Methods
        public bool OpenPDF(String filename)
        {
            try
            {
                try
                {
                    _pdfdoc = new PDFDoc(filename);
                }
                catch (Exception ex)
                {
                    _pdfdoc = OpenImage(filename);
                    if (_pdfdoc == null)
                        throw ex;
                }

                if (!_pdfdoc.InitSecurityHandler())
                {
                    MessageBox.Show("Document authentication error", "PDFViewWPF Error");
                    return false;
                }
                Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_continuous);
                Current_View.SetPageViewMode(PDFViewWPF.PageViewMode.e_fit_width);
                Current_View.SetUrlExtraction(false);

                if (_pdfdoc.GetPageCount() > 2000)
                {
                    Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_page);
                }
                Current_View.SetDoc(_pdfdoc);
                _sidecontrol.CreateSideWindow(Current_View, _ToolManager);
            }
            catch (PDFNetException ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }

            return true;
        }

        // A utility function used to display other images types besides PDF (TIF, JPEG, BMG,PNG, etc)
        public PDFDoc OpenImage(string filename)
        {
            try
            {
                PDFDoc pdfDoc = new PDFDoc();
                ElementBuilder f = new ElementBuilder();
                ElementWriter writer = new ElementWriter();

                pdftron.PDF.Page page = pdfDoc.PageCreate();
                writer.Begin(page);

                // Add image to the document
                pdftron.PDF.Image img = pdftron.PDF.Image.Create(pdfDoc, filename);

                pdftron.PDF.Rect imgBox = new pdftron.PDF.Rect(0, 0, img.GetImageWidth(), img.GetImageHeight());
                pdftron.PDF.Rect scaledBox = new pdftron.PDF.Rect();
                double scaleFactor;
                if (imgBox.Height() / imgBox.Width() > 792 / 612)
                    scaleFactor = imgBox.Height() / 792;
                else
                    scaleFactor = imgBox.Width() / 612;
                scaledBox.x2 = imgBox.x2 / scaleFactor;
                scaledBox.y2 = imgBox.y2 / scaleFactor;

                // set crop and media box of this page to fit with the scaled image 
                page.SetCropBox(scaledBox);
                page.SetMediaBox(scaledBox);

                // create the image element and add it to the page 
                int width = (int)scaledBox.Width();
                int height = (int)scaledBox.Height();
                int offsetX = 0;
                int offsetY = 0;

                Element element = f.CreateImage(img, new Matrix2D(width, 0, 0, height, offsetX, offsetY));
                writer.WritePlacedElement(element);
                writer.End(); // Finish writing to the page 

                pdfDoc.PagePushBack(page);
                return pdfDoc;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public bool OpenURL(String url, String password)
        {
            try
            {
                // Open a PDF file at the given url. This works best with PDF's that
                // are linearized, as pages can be downloaded and viewed in random access order,
                // without the need to download the entire document. A viewing session can also be
                // persisted across multiple viewing/application sessions to remove redundant downloads 
                // and improve overall performance by using the optional cache_file parameter.
                _ToolManager.IsEnabled = false;
                Current_View.OpenURLAsync(url, "", password);
            }
            catch (PDFNetException ex)
            {
                _ToolManager.IsEnabled = true;
                MessageBox.Show(ex.Message);
                return false;
            }
            catch (Exception ex)
            {
                _ToolManager.IsEnabled = true;
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }

        public PDFDoc GetPDFDoc()
        {
            if (_pdfdoc == null) return null;
            else return Current_View.GetDoc();
        }

        public void SetPageViewMode(PDFViewWPF.PageViewMode mode)
        {
            Current_View.SetPageViewMode(mode);
        }

        public PDFViewWPF.PageViewMode GetPageViewMode()
        {
            return Current_View.GetPageViewMode();
        }

        public void FitPage()
        {
            Current_View.SetPageViewMode(PDFViewWPF.PageViewMode.e_fit_page);
        }

        public void FitWidth()
        {
            Current_View.SetPageViewMode(PDFViewWPF.PageViewMode.e_fit_width);
        }

        public double GetZoom()
        {
            return Current_View.GetZoom();
        }

        public void SetZoom(double zoom)
        {
            Current_View.SetZoom(zoom);
        }

        public void ZoomIn()
        {
            Current_View.SetZoom(Current_View.GetZoom() * 1.25);
        }

        public void ZoomOut()
        {
            Current_View.SetZoom(Current_View.GetZoom() / 1.25);
        }

        public int GetCurrentPageNumber()
        {
            return Current_View.GetCurrentPage();
        }

        public void FirstPage()
        {
            Current_View.GotoFirstPage();
        }

        public void PrevPage()
        {
            Current_View.GotoPreviousPage();
        }

        public void NextPage()
        {
            Current_View.GotoNextPage();
        }

        public void LastPage()
        {
            Current_View.GotoLastPage();
        }

        public void PageSingle()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_page);
        }

        public void PageSingleContinuous()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_continuous);
        }

        public void PageFacingContinuous()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_facing_continuous);
        }

        public void PageFacing()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_facing);
        }

        public void PageFacingCover()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_facing_cover);
        }

        public void PageFacingCoverContinous()
        {
            Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_facing_continuous_cover);
        }

        public void RotateClockwise()
        {
            Current_View.RotateClockwise();
            Current_View.UpdatePageLayout();
            Current_View.Update();
        }

        public void RotateCounterClockwise()
        {
            Current_View.RotateCounterClockwise();
            //Current_View.UpdatePageLayout();
            //Current_View.Update();
        }

        public pdftron.PDF.Page.Rotate GetRotation()
        {
            return Current_View.GetRotation();
        }

        public void SetAntiAliasing(bool anti_alias)
        {
            Current_View.SetAntiAliasing(anti_alias);
            Current_View.Update();
        }

        public void SetRasterizer(bool built_in)
        {
            if (built_in)
                Current_View.SetRasterizerType(PDFRasterizer.Type.e_BuiltIn);
            else
                Current_View.SetRasterizerType(PDFRasterizer.Type.e_GDIPlus);

            Current_View.Update();
        }

        public void SetSmoothImages(bool smooth_images)
        {
            Current_View.SetImageSmoothing(smooth_images);
            Current_View.Update();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename">The path to save the file to</param>
        /// <param name="force">true if we should save, whether or not it is modified</param>
        public void Save(string filename, bool force = false)
        {
            if (_pdfdoc == null) return;

            System.IO.FileInfo fi = new System.IO.FileInfo(filename);
            if (fi.Exists && fi.IsReadOnly)
            {
                MessageBox.Show("This is a read only file. Please choose Save As and enter a new file name to save.", "Error during the Save");
                return;
            }

            bool locked = false;
            try
            {
                bool shouldSave = force;
                if (!shouldSave)
                {
                    Current_View.DocLock(true);
                    locked = true;
                    if (_pdfdoc.IsModified())
                    {
                        Current_View.DocUnlock();
                        locked = false;
                        shouldSave = true;
                    }
                }
                if (shouldSave)
                {
                    Current_View.CancelRendering();
                    _pdfdoc.Save(filename, pdftron.SDF.SDFDoc.SaveOptions.e_incremental);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error during the Save");
            }
            finally
            {
                if (locked)
                {
                    Current_View.DocUnlock();
                }
            }
        }

        public string SaveAs()
        {
            if (_pdfdoc != null && Current_View != null)
            {
                Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
                dlg.Filter = "PDF Files (*.pdf)|*.pdf|All Files (*.*)|*.*";
                dlg.DefaultExt = ".pdf";
                dlg.FileName = _pdfdoc.GetFileName();

                if (dlg.ShowDialog() == true)
                {
                    this.Save(dlg.FileName);
                    return dlg.SafeFileName;
                }
            }
            return null;
        }

        public bool CloseFile()
        {
            if (_pdfdoc != null && Current_View != null && _pdfdoc.IsModified())
            {
                string messageBoxText = "Would you like to save changes to " + _safeDocName + "?";
                string caption = "PDFViewWPF";
                MessageBoxButton button = MessageBoxButton.YesNoCancel;
                MessageBoxImage icon = MessageBoxImage.Question;
                MessageBoxResult defaultResult = MessageBoxResult.Yes;
                MessageBoxOptions options = MessageBoxOptions.DefaultDesktopOnly;

                MessageBoxResult result;
                result = MessageBox.Show(messageBoxText, caption, button, icon, defaultResult, options);

                if (result == MessageBoxResult.Yes)
                {
                    this.Save(_pdfdoc.GetFileName());
                    Dispose();
                    return true;
                }
                else if (result == MessageBoxResult.No)
                {
                    Dispose();
                    return true;
                }
                else
                    return false;
            }
            else
            {
                Dispose();
                return true;
            }
        }

        public void Dispose()
        {
            this.ToolManager.Close();
            Current_View.CloseDoc();
            Current_View.Dispose();
            Current_Main = null;
            _sidecontrol = null;
            if (_pdfdoc != null) _pdfdoc.Dispose();
        }

        public void Activate()
        {
            Current_View.Activate();
            _sidecontrol.Activate();

            _sidecontrol.UpdateLayout();
        }

        public void Deactivate()
        {
            if (Current_View != null)
            {
                Current_View.Deactivate();
            }
            if (_sidecontrol != null)
            {
                _sidecontrol.Deactivate();
            }
        }

        //public void SetToolMode(PDFViewWPF.ToolMode tool_mode)
        //{
        //    Current_View.SetToolMode(tool_mode);
        //}

        public void CopySelectedText()
        {
            Current_View.CopySelectedTextToClipboardAsUnicode();
        }

        public void SelectAll()
        {
            _ToolManager.CurrentTool.SelectAll();
        }

        public void DeselectAll()
        {
            _ToolManager.CurrentTool.DeselectAll();
        }

        public void FindText(string str, bool match_case, bool match_whole_word, bool search_up, bool reg_exp)
        {
            Current_View.FindText(str, match_case, match_whole_word, search_up, reg_exp); // Use the build in Find text dialog.
        }


        void Current_View_FindTextFinished(PDFViewWPF viewer, bool found, PDFViewWPF.Selection selection)
        {
            Current_Main.FindTextFinishedHandler(viewer, found, selection);
            _currentSearchSelection = selection;
            HighlightSelection();
            _ToolManager.ClearSelectedTextHighlighting();
        }

        /// <summary>
        /// Highlights the search result if any
        /// </summary>
        /// <param name="result">A text selection acquired by mPDFView.FindText</param>
        /// <returns>true if and only if the selections contains at least one highlight</returns>
        private bool HighlightSelection()
        {
            ClearSearchSelection();
            if (_currentSearchSelection == null)
            {
                return false;
            }

            double[] quads = _currentSearchSelection.GetQuads();
            int numQuads = quads.Length / 8;
            int pageNumber = _currentSearchSelection.GetPageNum();
            int quadNumber = 0;
            int[] visiblePages = Current_View.GetVisiblePages();
            if (!visiblePages.Contains(pageNumber))
            {
                return false;
            }

            List<System.Windows.Rect> rects = new List<System.Windows.Rect>();

            // get highlights in control (screen) space
            for (int i = 0; i < numQuads; i++)
            {
                quadNumber = i * 8;
                double x1 = quads[quadNumber + 0];
                double y1 = quads[quadNumber + 1];

                double x2 = quads[quadNumber + 2];
                double y2 = quads[quadNumber + 3];

                double x3 = quads[quadNumber + 4];
                double y3 = quads[quadNumber + 5];

                double x4 = quads[quadNumber + 6];
                double y4 = quads[quadNumber + 7];

                Current_View.ConvPagePtToScreenPt(ref x1, ref y1, pageNumber);
                Current_View.ConvPagePtToScreenPt(ref x2, ref y2, pageNumber);
                Current_View.ConvPagePtToScreenPt(ref x3, ref y3, pageNumber);
                Current_View.ConvPagePtToScreenPt(ref x4, ref y4, pageNumber);

                double left, right, top, bottom;

                left = Math.Min(x1, Math.Min(x2, Math.Min(x3, x4)));
                right = Math.Max(x1, Math.Max(x2, Math.Max(x3, x4)));
                top = Math.Min(y1, Math.Min(y2, Math.Min(y3, y4)));
                bottom = Math.Max(y1, Math.Max(y2, Math.Max(y3, y4)));

                rects.Add(new System.Windows.Rect(left, top, right - left, bottom - top));
            }

            Canvas annotCanvas = Current_View.GetCanvas();

            // add highlight(s) to annotation canvas
            foreach (System.Windows.Rect rect in rects)
            {
                Rectangle highlight = new Rectangle();
                highlight.Fill = new SolidColorBrush() { Color = Colors.Blue };
                highlight.Fill.Opacity = 0.3;
                highlight.Width = rect.Width;
                highlight.Height = rect.Height;
                Canvas.SetLeft(highlight, rect.Left + Current_View.GetHScrollPos());
                Canvas.SetTop(highlight, rect.Top + Current_View.GetVScrollPos());
                annotCanvas.Children.Add(highlight);
                _onScreenSelection.Add(highlight);
            }

            return numQuads > 0;
        }

        /// <summary>
        /// Removes the rectangles highlighting the selection, but keeps the selection for future reference
        /// to be used with HighlightSelection
        /// </summary>
        /// <param name="deleteSelection">If true, will also delete the underlaying selection</param>
        public void ClearSearchSelection(bool deleteSelection = false)
        {
            foreach (Rectangle rect in _onScreenSelection)
            {
                Canvas parent = rect.Parent as Canvas;
                if (parent != null)
                {
                    parent.Children.Remove(rect);
                }
            }
            if (deleteSelection)
            {
                _currentSearchSelection = null;
            }
        }

        public int GetPageCount()
        {
            return Current_View.GetPageCount();
        }

        private void OnDownload(DownloadedType type, Int32 page_num, Int32 obj_num, String msg, Object obj)
        {
            switch (type)
            {
                case DownloadedType.e_opened:
                    // e_opened indicates that we have a valid, but incomplete PDFDoc.
                    _pdfdoc = Current_View.GetDoc();
                    if (_pdfdoc.GetPageCount() > 2000)
                    {
                        Current_View.SetPagePresentationMode(PDFViewWPF.PagePresentationMode.e_single_page);
                    }
                    _sidecontrol.CreateSideWindow(Current_View, _ToolManager);
                    // the PDF should be treated as read only, and only simple functions
                    // should be called on the doc, until e_finished has been called.
                    Current_Main.PDFTab_UpdateCurrent();
                    break;
                case DownloadedType.e_page:
                    // this indicates the entire page is downloaded and it is safe to modify.
                    // for example add a new annotation
                    break;
                case DownloadedType.e_finished:
                    // we now have the full PDF file and it can be treated like any other
                    _ToolManager.IsEnabled = true;
                    if (MessageBox.Show("Download complete, would you like to save the PDF locally?",
                        "PDF Downloaded", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        SaveAs();
                    }
                    break;
                case DownloadedType.e_failed:
                    // downloading has stopped if this occurs
                    _ToolManager.IsEnabled = true;
                    MessageBox.Show(msg);
                    Current_Main.CloseViewer(this);
                    break;
            }
        }

        #endregion
    }
}
