using CommonAI.RTS;
using CommonLang.Vector;
using CommonLang;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CommonFroms.Drawing;

namespace GameEditorPlugin.Tools
{
    public partial class FormCollision : Form
    {
        public enum TestType
        {
            RoundLine,
            RoundLineW,
            RoundRect,
            LineLine,
            RoundInclude,
            FanRound,
        }
        private TestType test = TestType.RoundLine;
        private Random random = new Random();

        private Color pen1 = Color.FromArgb(0xFF, 0xFF, 0, 0);
        private Color pen2 = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);

        private CommonLang.Vector.Round s_round = new CommonLang.Vector.Round();
        private CommonLang.Vector.Line2 s_line = new CommonLang.Vector.Line2();
        private CommonLang.Vector.Fan s_fan = new CommonLang.Vector.Fan();

        private CommonLang.Vector.Line2 mouse_line = new CommonLang.Vector.Line2();
        private float line_r = 50;


        public FormCollision()
        {
            InitializeComponent();

            combo_TestType.Text = test.ToString();
            foreach (object obj in Enum.GetValues(typeof(TestType)))
            {
                combo_TestType.Items.Add(obj.ToString());
            }

            reset();
            //             {
            //                 s_round.x = 58.73995f;
            //                 s_round.y = 148.076263f;
            //                 s_round.r = 1f;
            // 
            //                 mouse_line.p.x = 61.67477f;
            //                 mouse_line.p.y = 148.0653f;
            //                 mouse_line.q.x = 51.67484f;
            //                 mouse_line.q.y = 148.102631f;
            // 
            //                 line_r = 0.15f;
            //             }
        }
        private void btn_Reset_Click(object sender, EventArgs e)
        {
            reset();
            pictureBox1.Refresh();
        }
        private void reset()
        {
            int w = pictureBox1.Width;
            int h = pictureBox1.Height;

            s_round.x = random.Next(200, w - 400);
            s_round.y = random.Next(200, h - 400);
            s_round.r = random.Next(10, 200);

            s_line.p.SetX(random.Next(100, w - 200));
            s_line.p.SetY(random.Next(100, h - 200));
            s_line.q.SetX(random.Next(100, w - 200));
            s_line.q.SetY(random.Next(100, h - 200));

            s_fan.x = random.Next(200, w - 400);
            s_fan.y = random.Next(200, h - 400);
            s_fan.r = random.Next(10, 200);
            s_fan.direction = ((float)random.NextDouble() * CMath.PI_MUL_2);
            s_fan.angle_range = ((float)random.NextDouble() * CMath.PI_F);

            line_r = random.Next(10, 100);
        }

        private void combo_TestType_TextChanged(object sender, EventArgs e)
        {
            TestType value;
            if (Enum.TryParse<TestType>(combo_TestType.Text, out value))
            {
                test = value;
                reset();
                pictureBox1.Refresh();
            }
        }
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                mouse_line.q.SetX(e.X);
                mouse_line.q.SetY(e.Y);
                pictureBox1.Refresh();
            }
        }
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            pictureBox1.Focus();
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                mouse_line.p.SetX(e.X);
                mouse_line.p.SetY(e.Y);
                mouse_line.q.SetX(e.X);
                mouse_line.q.SetY(e.Y);
                pictureBox1.Refresh();
            }
        }
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                mouse_line.q.SetX(e.X);
				mouse_line.q.SetY(e.Y);
				pictureBox1.Refresh();
            }
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillRectangle(new SolidBrush(Color.Black), pictureBox1.DisplayRectangle);
            switch (test)
            {
                case TestType.RoundLine:
                    drawRoundLine(e.Graphics);
                    break;
                case TestType.RoundLineW:
                    drawRoundLineW(e.Graphics);
                    break;
                case TestType.RoundRect:
                    drawRectRound(e.Graphics);
                    break;
                case TestType.LineLine:
                    drawLineLine(e.Graphics);
                    break;
                case TestType.RoundInclude:
                    drawRoundInclude(e.Graphics);
                    break;
                case TestType.FanRound:
                    drawFanRound(e.Graphics);
                    break;
            }
        }

        private bool intersetctLineLine()
        {
            return CMath.intersectLine(s_line.p.X, s_line.p.Y, s_line.q.X, s_line.q.Y, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
        }
        private bool intersectRectRound()
        {
            float sx = Math.Min(mouse_line.p.X, mouse_line.q.X);
            float sy = Math.Min(mouse_line.p.Y, mouse_line.q.Y);
            float dx = Math.Max(mouse_line.p.X, mouse_line.q.X);
            float dy = Math.Max(mouse_line.p.Y, mouse_line.q.Y);
            return CMath.intersectRectRound(sx, sy, dx, dy, s_round.x, s_round.y, s_round.r);
        }
        private bool intersetctRoundLine()
        {
            return CMath.intersectRoundStripCapsule(s_round.x, s_round.y, s_round.r, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y, line_r);
        }
        private bool intersetctRoundLineW()
        {
            return CMath.intersectRoundStripWidth(s_round.x, s_round.y, s_round.r, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y, line_r);
        }
        private bool includeRound()
        {
            float dr = CMath.getDistance(mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
            return CMath.includeRound2(s_round.x, s_round.y, s_round.r, mouse_line.p.X, mouse_line.p.Y, dr);
        }
        private bool intersectFanRound()
        {
            return CMath.intersectFanRound(
                s_fan.x, s_fan.y, s_fan.r,
                mouse_line.q.X, mouse_line.q.Y, line_r,
                s_fan.direction - s_fan.angle_range / 2,
                s_fan.direction + s_fan.angle_range / 2);
        }

        private void drawLineLine(Graphics g)
        {
            Color color = intersetctLineLine() ? pen2 : pen1;
            // sline
            {
                Pen pen = new Pen(color);
                g.DrawLine(pen, s_line.p.X, s_line.p.Y, s_line.q.X, s_line.q.Y);
            }
            // line move
            {
                Pen pen = new Pen(color);
                g.DrawLine(pen, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
            }
        }
        private void drawRectRound(Graphics g)
        {
            Color color = intersectRectRound() ? pen2 : pen1;
            // round
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillEllipse(bursh, s_round.x - s_round.r, s_round.y - s_round.r, s_round.r * 2f, s_round.r * 2f);
            }
            {
                SolidBrush bursh = new SolidBrush(color);
                float sx = Math.Min(mouse_line.p.X, mouse_line.q.X);
                float sy = Math.Min(mouse_line.p.Y, mouse_line.q.Y);
                float dx = Math.Max(mouse_line.p.X, mouse_line.q.X);
                float dy = Math.Max(mouse_line.p.Y, mouse_line.q.Y);
                g.FillRectangle(bursh, sx, sy, dx - sx, dy - sy);
            }

        }
        private void drawRoundLine(Graphics g)
        {
            Color color = intersetctRoundLine() ? pen2 : pen1;
            // round
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillEllipse(bursh, s_round.x - s_round.r, s_round.y - s_round.r, s_round.r * 2f, s_round.r * 2f);
            }
            // line move
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillEllipse(bursh, mouse_line.p.X - line_r, mouse_line.p.Y - line_r, line_r * 2f, line_r * 2f);
                g.FillEllipse(bursh, mouse_line.q.X - line_r, mouse_line.q.Y - line_r, line_r * 2f, line_r * 2f);
                Pen pen = new Pen(color);
                pen.Width = line_r * 2f;
                g.DrawLine(pen, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
            }
        }
        private void drawRoundLineW(Graphics g)
        {
            Color color = intersetctRoundLineW() ? pen2 : pen1;
            // round
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillEllipse(bursh, s_round.x - s_round.r, s_round.y - s_round.r, s_round.r * 2f, s_round.r * 2f);
            }
            // line move
            {
                Pen pen = new Pen(color);
                pen.Width = line_r * 2f;
                g.DrawLine(pen, mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
            }
        }
        private void drawRoundInclude(Graphics g)
        {
            Color color = includeRound() ? pen2 : pen1;
            // round
            {
                Pen pen = new Pen(color);
                g.DrawEllipse(pen, s_round.x - s_round.r, s_round.y - s_round.r, s_round.r * 2f, s_round.r * 2f);
            }
            // line move
            {
                Pen pen = new Pen(color);
                float dr = CMath.getDistance(mouse_line.p.X, mouse_line.p.Y, mouse_line.q.X, mouse_line.q.Y);
                g.DrawEllipse(pen, mouse_line.p.X - dr, mouse_line.p.Y - dr, dr * 2, dr * 2);
            }
        }
        private void drawFanRound(Graphics g)
        {
            Color color = intersectFanRound() ? pen2 : pen1;
            // fan
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillPie(bursh,
                    s_fan.x - s_fan.r,
                    s_fan.y - s_fan.r,
                    s_fan.r * 2,
                    s_fan.r * 2,
                    CMath.RadiansToDegrees(CMath.PI_MUL_2 + s_fan.direction - s_fan.angle_range / 2),
                    CMath.RadiansToDegrees(s_fan.angle_range));
            }
            // round
            {
                SolidBrush bursh = new SolidBrush(color);
                g.FillEllipse(bursh, mouse_line.q.X - line_r, mouse_line.q.Y - line_r, line_r * 2f, line_r * 2f);
            }
        }
    }
}