using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace bbiwarg.Utility
{
    public enum LineSide
    {
        onLine = 0,
        above = 1,
        below = 2
    }

    class Line2D
    {
        public Vector2D PointOnLine { get; private set; }
        public Vector2D Direction { get; private set; }

        public Line2D(Vector2D pointOnLine, Vector2D direction)
        {
            PointOnLine = pointOnLine;
            Direction = direction.normalize();
        }

        public float getAngleBetween(Line2D line)
        {
            float angle = Direction.getAngleBetween(line.Direction);
            return Math.Min(angle, 180 - angle);
        }

        public LineSide onSide(Vector2D point)
        {
            float yPerX = Direction.Y / Direction.X;
            float xDiff = point.X - PointOnLine.X;
            float newY = PointOnLine.Y + yPerX * xDiff;
            if (newY < point.Y) return LineSide.above;
            else if (newY > point.Y) return LineSide.below;
            else return LineSide.onLine;
        }

        public Vector2D projectToLine(Vector2D point)
        {
            float px = point.X, py = point.Y, dx = Direction.X, dy = Direction.Y, ox = PointOnLine.X, oy = PointOnLine.Y;
            float diffx = px - ox;
            float diffy = py - oy;

            float diff_d = (diffx * dx + diffy * dy);
            float d_d = (dx * dx + dy * dy);
            float q = diff_d / d_d;

            float newX = ox + q * dx;
            float newY = oy + q * dy;

            return new Vector2D(newX, newY);
        }

        public Vector2D getIntersection(Line2D line)
        {
            Vector2D p = PointOnLine;
            Vector2D r = Direction;
            Vector2D q = line.PointOnLine;
            Vector2D s = line.Direction;

            float r_cross_s = r.cross(s);
            float q_p_cross_s = (q - p).cross(s);

            if (r_cross_s == 0.0)
                return null;

            float t = q_p_cross_s / r_cross_s;
            return p + t * r;
        }

    }
}
