using System.Runtime.InteropServices;
using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Rectangle;

using OpenCvSharp;
using Point = OpenCvSharp.Point;

namespace Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.RotatedRectangle;

public class RotatedRectangleElement:IGraphicsElement
{
    public bool Editable { get; set; }
    public bool IsGood { get; set; }

    public Vector2 Location { get; set; }
    public Vector2 Offset { get; set; }

    public Vector2 Height { get; set; }
    public float HalfWidth { get; set; }


    public void Draw(ICanvas canvas)
    {
        var type = IsGood ? LineType.Good : LineType.Bad;
        var perpendicular = new Vector2(Height.Y, -Height.X);
        perpendicular.Normalize();

        canvas.DrawLine(Offset + Location - perpendicular * HalfWidth, Offset + Location+perpendicular*HalfWidth, type);
        canvas.DrawLine(Offset + Location + Height - perpendicular * HalfWidth, Offset + Location + Height + perpendicular * HalfWidth, type);
        canvas.DrawLine(
            Offset + Location + perpendicular * HalfWidth
            , Offset + Location + Height + perpendicular * HalfWidth
            , type);
        canvas.DrawLine(
            Offset + Location - perpendicular * HalfWidth
            , Offset + Location + Height - perpendicular * HalfWidth
            , type);
        canvas.DrawNode(Offset + Location);
        canvas.DrawNode(Offset + Location + Height);
        canvas.DrawNode(Offset + Location + Height + perpendicular * HalfWidth);

        canvas.DrawArrow(Offset + Location, Height);

    }

    public void FillMat(Mat mat)
    {
        var perpendicular = new Vector2(Height.Y, -Height.X);
        perpendicular.Normalize();
        var p1 = Offset + Location - perpendicular * HalfWidth;
        var p2 = Offset + Location + perpendicular * HalfWidth;
        var p3 = Offset + Location + Height + perpendicular * HalfWidth;
        var p4 = Offset + Location + Height - perpendicular * HalfWidth;
        mat.FillPoly(new IEnumerable<Point>[]
     {
         new List<Point>()
         {
             new Point(p1.X,p1.Y),
             new Point(p2.X,p2.Y),
             new Point(p3.X,p3.Y),
             new Point(p4.X,p4.Y),
         }
     },Scalar.White);
    }


    public INode? GetNode(Vector2 position, float thDistance)
    {
        if ((Location + Offset - position).Length() < thDistance)
        {
            return new RotatedRectangleAnchorNode(this);
        }
        if ((Height + Location + Offset - position).Length() < thDistance)
        {
            return new RotatedRectangleHeightNode(this);
        }

        var perpendicular = new Vector2(Height.Y, -Height.X);
        perpendicular.Normalize();
        if (((Offset + Location + Height + perpendicular * HalfWidth) - position).Length() < thDistance)
        {
            return new RotatedRectangleHalfWidthNode(this);
        }
        return null;
    }

    public void SetPivot(Vector2 pivot)
    {
        Location += Offset;
        Offset = pivot;
        Location -= Offset;
    }

    public void MovePivot(Vector2 pivot)
    {
        Offset = pivot;
    }




    public void Save(BinaryWriter bw)
    {
        bw.Write(Editable);
        bw.Write(IsGood);
        bw.Write(Location.X);
        bw.Write(Location.Y);
        bw.Write(Offset.X);
        bw.Write(Offset.Y);
        bw.Write(Height.X);
        bw.Write(Height.Y);
        bw.Write(HalfWidth);
    }

    public void Load(BinaryReader br)
    {
        Editable = br.ReadBoolean();
        IsGood = br.ReadBoolean();
        Location = new Vector2(br.ReadSingle(), br.ReadSingle());
        Offset = new Vector2(br.ReadSingle(), br.ReadSingle());
        Height = new Vector2(br.ReadSingle(), br.ReadSingle());
        HalfWidth = br.ReadSingle();
    }
}