using System;
using System.Collections.Generic;
using System.Text;
using nft.framework.drawing;
using nft.impl.game;
using nft.core.geometry;
using nft.core;
using Geocon = nft.core.geometry.GeometricConstants;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using nft.core.game;

namespace nft.impl.view
{
    public class GameViewPanel : UserControl
    {
        SceneBuilder builder;
        public GameViewPanel(GameImpl game) {
            InitializeComponent();
            //renderPanel.SurfaceUsage = SurfaceUsage.Normal;
            touchPanel.Scroll2 += new ScrollEventHandler(OnTouchPanelScroll);
            builder = new SceneBuilder(game);
            renderPanel.OnSurfacePrepared += new EventHandler(SurfaceReady);
        }

        void EventTarget_MouseMove(object sender, MouseEventArgs e) {
            //UInt32 u = renderPanel.Surface.HitTestAt(e.X, e.Y);
            object o = builder.GetObjectAt(e.Location);
            renderPanel.Refresh();
        }

        public SceneBuilder SceneBuilder {
            get { return builder; }
        }

        public InterCardinalDirection UpperDirection {
            get { return builder.UpperDirection; }
            set { 
                builder.UpperDirection = value;
                this.Refresh();
            }
        }

        void OnTouchPanelScroll(object sender, ScrollEventArgs e) {
            UpdateScrollParams(false);
        }

        void SurfaceReady(object sender, EventArgs e) {
            builder.AttachSurface(renderPanel.Surface);
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);
            this.SuspendLayout();
            Size sz = ClientSize;
            Size szu = new Size(Geocon.UnitWidthPixel, Geocon.HalfOf_UnitWidthPixel);
            Size szc = builder.ContentSize;
            InitScroll(szc, szu);
            renderPanel.EventTarget.MouseMove += new MouseEventHandler(EventTarget_MouseMove);
            this.ResumeLayout(false);
        }

        #region Designer generated
        private TouchPanel touchPanel;
        private RenderViewPanel renderPanel;
        private Panel panelDummy;
        private void InitializeComponent() {
            this.renderPanel = new nft.framework.drawing.RenderViewPanel();
            this.touchPanel = new nft.impl.view.TouchPanel();
            this.panelDummy = new System.Windows.Forms.Panel();
            this.touchPanel.SuspendLayout();
            this.SuspendLayout();
            // 
            // renderPanel
            // 
            this.renderPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.renderPanel.Location = new System.Drawing.Point(0, 0);
            this.renderPanel.Name = "renderPanel";
            this.renderPanel.Size = new System.Drawing.Size(150, 150);
            this.renderPanel.SurfaceUsage = nft.framework.drawing.SurfaceUsage.GameView;
            this.renderPanel.TabIndex = 1;
            // 
            // touchPanel
            // 
            this.touchPanel.AutoScroll = true;
            this.touchPanel.BackColor = System.Drawing.Color.Transparent;
            this.touchPanel.Controls.Add(this.panelDummy);
            this.touchPanel.Dock = System.Windows.Forms.DockStyle.Fill;
            this.touchPanel.Location = new System.Drawing.Point(0, 0);
            this.touchPanel.Name = "touchPanel";
            this.touchPanel.Size = new System.Drawing.Size(150, 150);
            this.touchPanel.TabIndex = 0;
            // 
            // panelDummy
            // 
            this.panelDummy.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.panelDummy.Location = new System.Drawing.Point(0, 0);
            this.panelDummy.Name = "panelDummy";
            this.panelDummy.Size = new System.Drawing.Size(150, 150);
            this.panelDummy.TabIndex = 0;
            // 
            // GameViewPanel
            // 
            this.Controls.Add(this.renderPanel);
            this.Controls.Add(this.touchPanel);
            this.Name = "GameViewPanel";
            this.touchPanel.ResumeLayout(false);
            this.ResumeLayout(false);

        }
        #endregion

        #region Scroll management
        Point offset = new Point();
        protected virtual void InitScroll(Size contentSize, Size scrollUnit) {
            touchPanel.AutoScrollMinSize = contentSize;
            UpdateScrollParams(true);
            Rectangle r = VisibleBounce;
            int w = Math.Max(0, (contentSize.Width - r.Width) / 2);
            int h = Math.Max(0,(contentSize.Height - r.Height) / 2);
            touchPanel.AutoScrollPosition = new Point(w,h);
        }

        public Rectangle VisibleBounce {
            get {
                if (panelDummy != null) {
                    Control c = panelDummy;
                    Rectangle rect = c.RectangleToScreen(c.ClientRectangle);
                    Control c2 = c.Parent;
                    rect = Rectangle.Intersect(rect, c2.RectangleToScreen(c2.ClientRectangle));
                    rect = c.RectangleToClient(rect);
                    return rect;
                } else {
                    return touchPanel.ClientRectangle;
                }
            }
        }

        public void UpdateScrollParams(bool resized) {
            SuspendLayout();
            Rectangle rvw = VisibleBounce;
            if (resized) {
                Size szcl = ClientSize;
                Size szmap = builder.ContentSize;
                Debug.WriteLine("map="+szmap+", cln="+szcl);
                int w2 = szcl.Width / 2;
                int h2 = szcl.Height / 2;
                offset.X = Math.Max(0, (szmap.Width - rvw.Width) / 2);
                offset.Y = Math.Max(0, szmap.Height - rvw.Height / 2);
                Debug.Write(", ofst=" + offset);
                renderPanel.Size = rvw.Size;
            }
            Point pt = touchPanel.AutoScrollPosition;
            Debug.Write(", scrl=" + pt);
            pt.Offset(offset);
            builder.ViewPosition = pt;
            Debug.WriteLine(", vwps="+pt);
            //Debug.WriteLine("VisibleRegion=" + rvw);
            ResumeLayout(true);
            renderPanel.Refresh();
        }

        protected Point ControlToContentPosition(int x, int y) {
            Point p = touchPanel.AutoScrollPosition;
            return new Point(x-p.X,y-p.Y);
        }

        protected override void OnSizeChanged(EventArgs e) {
            base.OnSizeChanged(e);
            Rectangle r = VisibleBounce;
            UpdateScrollParams(true);
        }

        protected override void OnPaintBackground(PaintEventArgs e) {
        }
        #endregion
    }

    /// <summary>
    /// For scroll bar management
    /// </summary>
    class TouchPanel : Panel
    {
        public event ScrollEventHandler Scroll2;
        
        protected override void OnScroll(ScrollEventArgs se) {
            if (Scroll2 != null) {
                // Because of unknown reason, we should draw both before and after OnScroll.
                // otherwize the view does not redrawed by the latest scroll position.
                Scroll2(this, se);
                base.OnScroll(se);
                Scroll2(this, se);
            } else {
                base.OnScroll(se);
            }
        }

        protected override void OnPaint(PaintEventArgs e) {
        }

        protected override void OnPaintBackground(PaintEventArgs e) {
        }
    }
}
