using System;
using System.Drawing;

namespace Tutor_RT
{
    public class V3
    {
        public double X;
        public double Y;
        public double Z;

        #region Constructors

        public V3()
        {
            this.X = 0;
            this.Y = 0;
            this.Z = 0;
        }

        public V3(double x, double y, double z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }

        #endregion

        #region Operators

        public override bool Equals(object obj)
        {
            return this.Equals(obj as V3);
        }

        public override int GetHashCode()
        {
            return ((int)X * 0x1ab) + ((int)Y * 0x1a) + (int)Z + 17;
        }

        public static bool operator ==(V3 v1, V3 v2)
        {
            return v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z;
        }

        public static bool operator !=(V3 v1, V3 v2)
        {
            return !(v1 == v2);
        }

        public static V3 operator +(V3 v1, V3 v2)
        {
            return new V3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
        }

        public static V3 operator -(V3 v)
        {
            return new V3(-v.X, -v.Y, -v.Z);
        }

        public static V3 operator -(V3 v1, V3 v2)
        {
            return new V3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
        }

        public static double operator *(V3 v1, V3 v2)
        {
            return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
        }

        public static V3 operator *(V3 v, double factor)
        {
            return new V3(v.X * factor, v.Y * factor, v.Z * factor);
        }

        public static V3 operator *(double factor, V3 v)
        {
            return new V3(v.X * factor, v.Y * factor, v.Z * factor);
        }

        public static V3 operator /(V3 v, double divider)
        {
            return new V3(v.X / divider, v.Y / divider, v.Z / divider);
        }

        public static V3 operator ^(V3 v1, V3 v2)
        {
            return new V3(v1.Y * v2.Z - v2.Y * v1.Z, -(v1.X * v2.Z - v2.X * v1.Z), v1.X * v2.Y - v2.X * v1.Y);
        }

        #endregion

        #region Properties

        public Double Length
        {
            get { return System.Math.Sqrt(X * X + Y * Y + Z * Z); }
        }

        public V3 normalize
        {
            get { return new V3(X / Length, Y / Length, Z / Length); }
        }

        #endregion

        public String Text()
        {
            return System.String.Format("[{0:0.##}/{1:0.##}/{2:0.##}]", X, Y, Z);
        }

        public static int print_v(Graphics g, V3 v, int t_xpos, int t_ypos)
        {//v[row]
            Font fn = new Font("Consolas", 16, FontStyle.Italic);
            Brush br = new SolidBrush(Color.Blue);
            Pen pe = new Pen(Brushes.Blue, 2);
            int i, t_dy = 25, ax = 0, xpos = t_xpos + 10, ypos = t_ypos;
            SizeF SF;
            String precision = "0.###";
            double[] m = new double[] { v.X, v.Y, v.Z };
            //determin text_size of vector
            ax = 0;
            for (i = 0; i < 3; i++)//nr. of row
            {
                SF = g.MeasureString(m[i].ToString(precision), fn);
                if (((int)SF.Width) > ax) ax = (int)SF.Width;
            }
            //print column of the vector
            for (i = 0; i < 3; i++)//nr. of row
            {
                g.DrawString(m[i].ToString(precision), fn, br, xpos, ypos + 6 + t_dy * i);
            }
            xpos += ax;
            g.DrawBezier(pe, new Point(t_xpos + 10, t_ypos + 5), new Point(t_xpos, t_ypos + 10),
                             new Point(t_xpos, t_ypos + 85), new Point(t_xpos + 10, t_ypos + 90));
            g.DrawBezier(pe, new Point(xpos, t_ypos + 5), new Point(xpos + 10, t_ypos + 10),
                             new Point(xpos + 10, t_ypos + 85), new Point(xpos, t_ypos + 90));
            return xpos;
        }

        public static int print_dot(Graphics g, int t_xpos, int t_ypos)
        {
            Font fn = new Font("Consolas", 16, FontStyle.Italic);
            Brush br = new SolidBrush(Color.Blue);
            int xpos = t_xpos + 6, ypos = t_ypos;
            g.DrawString(".", fn, br, xpos, ypos + 26);
            return xpos + 18;
        }

        public static int print_num(Graphics g, double val, int t_xpos, int t_ypos)
        {
            Font fn = new Font("Consolas", 16, FontStyle.Italic);
            Brush br = new SolidBrush(Color.Blue);
            int xpos = t_xpos + 10, ypos = t_ypos;
            g.DrawString(val.ToString("0.###"), fn, br, xpos - 15, ypos + 31);
            return xpos + 10;
        }

        public static int print_dot_prod(Graphics g, V3 u, V3 v, int t_xpos, int t_ypos)
        {
            int x1 = t_xpos, y1 = t_ypos;
            x1 = print_v(g, u, x1, y1);
            x1 = print_dot(g, x1, y1);
            x1 = print_v(g, v, x1, y1);
            x1 = print_equal(g, x1, y1);
            x1 = print_num(g, u * v, x1, y1);
            return x1 + 10;
        }

        public static int print_cross_prod(Graphics g, V3 u, V3 v, int t_xpos, int t_ypos)
        {
            int x1 = t_xpos, y1 = t_ypos;
            x1 = print_v(g, u, x1, y1);
            x1 = print_x(g, x1, y1);
            x1 = print_v(g, v, x1, y1);
            x1 = print_equal(g, x1, y1);
            x1 = print_v(g, u ^ v, x1, y1);
            return x1 + 10;
        }

        public static int print_x(Graphics g, int t_xpos, int t_ypos)
        {
            Font fn = new Font("Consolas", 16, FontStyle.Italic);
            Brush br = new SolidBrush(Color.Blue);
            int xpos = t_xpos + 10, ypos = t_ypos;
            g.DrawString("\x00d7", fn, br, xpos, ypos + 31);
            return xpos + 25;
        }

        public static int print_equal(Graphics g, int t_xpos, int t_ypos)
        {
            Font fn = new Font("Consolas", 16, FontStyle.Italic);
            Brush br = new SolidBrush(Color.Blue);
            int xpos = t_xpos + 10, ypos = t_ypos;
            g.DrawString("=", fn, br, xpos, ypos + 31);
            return xpos + 25;
        }

    }

}
