using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace nft.framework.drawing
{
    /// <summary>
    /// Wrapper control for ISurface holder.
    /// </summary>
    public partial class RenderViewPanel : UserControl
    {
        protected ISurface surface;
        protected Control eventtarget;
        protected SurfaceUsage usage = SurfaceUsage.Normal;
        public event EventHandler OnSurfacePrepared;

        public RenderViewPanel()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (DesignMode)
            {
                Label label = new System.Windows.Forms.Label();
                label.Text = this.GetType().Name + " does not work in Desing mode.";
                label.TextAlign = ContentAlignment.MiddleCenter;
                label.BackColor = Color.CornflowerBlue;
                label.ForeColor = Color.White;
                label.Dock = DockStyle.Fill;
                this.Controls.Add(label);
                eventtarget = label;
            }
            else
            {
                IGraphicManager gm = (IGraphicManager)GlobalModules.GetModule(typeof(IGraphicManager));
                surface = gm.CreateSurfaceForControl(this, out eventtarget, usage);
                
                // Disable control to all events are processed by parent.
                eventtarget.Enabled = false;
                eventtarget = this;
                if (OnSurfacePrepared != null)
                    OnSurfacePrepared(this, new EventArgs());
            }
        }
       
        public ISurface Surface
        {
            get { return surface; }
        }

        /// <summary>
        /// Recommended to attach Mouse/Key event handlers instead of attach to this object directly.
        /// </summary>
        public Control EventTarget
        {
            get { return eventtarget; }
        }

        public SurfaceUsage SurfaceUsage {
            get {
                return usage;
            }
            set {
                if (surface != null) {
                    throw new InvalidOperationException("SurfaceUsage can change only before load.");
                }
                usage = value;
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e) {
        }
    }

    public class ScrollableRenderViewPanel : RenderViewPanel
    {
        private Size _scrollUnit;
        public ScrollableRenderViewPanel() : base(){        
        }

        protected void InitScroll(Size contentSize) {
            InitScroll(contentSize, new Size(), new Point(contentSize.Width / 2, contentSize.Height / 2));
        }
        protected void InitScroll(Size contentSize, Size scrollUnit) {
            InitScroll(contentSize, scrollUnit, new Point(contentSize.Width / 2, contentSize.Height / 2));
        }

        protected virtual void InitScroll(Size contentSize, Size scrollUnit, Point initialPos) {
            AutoScroll = true;
            this._scrollUnit = scrollUnit;
            if (scrollUnit.Height > 0) {
                VerticalScroll.SmallChange = scrollUnit.Height;
            }
            if (scrollUnit.Width > 0) {
                HorizontalScroll.SmallChange = scrollUnit.Width;
            }
            AutoScrollMinSize = contentSize;
            AutoScrollPosition = initialPos;
            UpdateScrollParams(true);
        }

        protected void UpdateScrollParams(bool resized) {
            if (Surface == null) return;
            Size szcl = ClientSize;
            int w2 = szcl.Width / 2;
            int h2 = szcl.Height / 2;
            if(resized){
                AutoScrollOffset = new Point(w2, h2);
            }
            if (_scrollUnit.Height <= 0) {
                VerticalScroll.SmallChange = h2;
            }
            if (_scrollUnit.Width <= 0) {
                HorizontalScroll.SmallChange = w2;
            }
            Size szsc = AutoScrollMinSize;
            Debug.WriteLine(string.Format("scrollsize=({0}x{1}), scrolloffset=({2},{3})", szsc.Width, szsc.Height, szcl.Width / 2, szcl.Height / 2));
        }

        protected override void OnClientSizeChanged(EventArgs e) {
            base.OnClientSizeChanged(e);
            UpdateScrollParams(true);
            Rectangle rct = ClientRectangle;
            Debug.WriteLine(string.Format("OnClientSizeChanged=({0}x{1})", rct.Width, rct.Height));
        }

        protected virtual PointF3D CalcCameraPosition() {
            Point pos = AutoScrollPosition;
            int h = pos.Y - AutoScrollOffset.Y;
            return new PointF3D(pos.X, h, 0);
        }
    }
}
