using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace DeepZoomOutput
{
    public partial class Page : UserControl
    {
        //
        // Based on prior work done by Lutz Gerhard, Peter Blois, and Scott Hanselman
        //
        Point lastMousePos = new Point();

        double _zoom = 1;
        bool mouseButtonPressed = false;
        bool mouseIsDragging = false;
        Point dragOffset;
        Point currentPosition;

        public double ZoomFactor
        {
            get { return _zoom; }
            set { _zoom = value; }
        }

        public Page()
        {

            InitializeComponent();
            this.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (mouseButtonPressed)
                {
                    mouseIsDragging = true;
                }
                this.lastMousePos = e.GetPosition(this.msi);
            };

            this.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
            {
                mouseButtonPressed = true;
                mouseIsDragging = false;
                dragOffset = e.GetPosition(this);
                currentPosition = msi.ViewportOrigin;
            };

            this.msi.MouseLeave += delegate(object sender, MouseEventArgs e)
            {
                mouseIsDragging = false;
            };

            this.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                mouseButtonPressed = false;
                if (mouseIsDragging == false)
                {
                    bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;

                    ZoomFactor = 2.0;
                    if (shiftDown) ZoomFactor = 0.5;
                    Zoom(ZoomFactor, this.lastMousePos);
                }
                mouseIsDragging = false;
            };

            this.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (mouseIsDragging)
                {
                    Point newOrigin = new Point();
                    newOrigin.X = currentPosition.X - (((e.GetPosition(msi).X - dragOffset.X) / msi.ActualWidth) * msi.ViewportWidth);
                    newOrigin.Y = currentPosition.Y - (((e.GetPosition(msi).Y - dragOffset.Y) / msi.ActualHeight) * msi.ViewportWidth);
                    msi.ViewportOrigin = newOrigin;
                }
            };

            new MouseWheelHelper(this).Moved += delegate(object sender, MouseWheelEventArgs e)
            {
                e.Handled = true;
                if (e.Delta > 0)
                    ZoomFactor = 1.2;
                else
                    ZoomFactor = .80;

                Zoom(ZoomFactor, this.lastMousePos);
            };
        }

        public void Zoom(double zoom, Point pointToZoom)
        {
            Point logicalPoint = this.msi.ElementToLogicalPoint(pointToZoom);
            this.msi.ZoomAboutLogicalPoint(zoom, logicalPoint.X, logicalPoint.Y);
        }

        private void Full_Size(object sender, RoutedEventArgs e)
        {
            msi.Width = Application.Current.Host.Content.ActualWidth;
            msi.Height = Application.Current.Host.Content.ActualHeight;
        }
    }
}
