Vector2DrawQuad
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description functions to handle vector2 Quad drawing operations.
library(title='Vector2DrawQuad')
// .
// references:
//      https://docs.unity3d.com/ScriptReference/Vector2.html
//      https://gist.github.com/winduptoy/a1aa09c3499e09edbd33
//      https://github.com/dogancoruh/Javascript-Vector2/blob/master/js/vector2.js
//      https://gist.github.com/Dalimil/3daf2a0c531d7d030deb37a7bfeff454
//      https://gist.github.com/jeantimex/7fa22744e0c45e5df770b532f696af2d
//      https://gist.github.com/volkansalma/2972237
// .



//#region ~~~ Imports:

import RicardoSantos/CommonTypesMath/1 as TMath
import RicardoSantos/CommonTypesDrawing/1 as TDraw
import RicardoSantos/Vector2/1 as Vector2
import RicardoSantos/Vector2DrawLine/1 as line

//#endregion



//#region   -> Constructor:

// new            () {

// @function Draws a quadrilateral with background fill.
// @param a          v2     . Vector2 object, in the form `(x, y)`.
// @param b          v2     . Vector2 object, in the form `(x, y)`.
// @param c          v2     . Vector2 object, in the form `(x, y)`.
// @param d          v2     . Vector2 object, in the form `(x, y)`.
// @param xloc       string . Type of axis unit, bar_index or time.
// @param bg_color   color  . Color of the background.
// @param line_color color  . Color of the line.
// @param line_style string . Style of the line.
// @param line_width int    . Width of the line.
// @returns Quad object.
export new (
 TMath.Vector2 a                     , 
 TMath.Vector2 b                     , 
 TMath.Vector2 c                     , 
 TMath.Vector2 d                     , 
 string        xloc       = 'bi'     , 
 color         bg_color   = #2196f3, 
 color         line_color = #2196f3, 
 string        line_style = 'sol'    , 
 int           line_width = 1        ) =>
    TMath.Segment2 _ab = TMath.Segment2.new(a, b)
    TMath.Segment2 _bc = TMath.Segment2.new(b, c)
    TMath.Segment2 _cd = TMath.Segment2.new(d, c) // the origin/target are inverted because of the fill
    TMath.Segment2 _da = TMath.Segment2.new(d, a)
    line _line1 = line.new(_ab, xloc, extend.none, line_color, line_style, line_width)
    line _line2 = line.new(_bc, xloc, extend.none, line_color, line_style, line_width)
    line _line3 = line.new(_cd, xloc, extend.none, line_color, line_style, line_width)
    line _line4 = line.new(_da, xloc, extend.none, line_color, line_style, line_width)
    linefill _fill = linefill.new(_line1, _line3, bg_color)
    TDraw.Quad.new(_line1, _line2, _line3, _line4, _fill)

// TEST: 20230220 RS
// if barstate.islast
//     _qa = Vector2.new(bar_index + 0.0, 0.0)
//     _qb = Vector2.new(bar_index + 0.0, 100.0)
//     _qc = Vector2.new(bar_index + 100.0, 100.0)
//     _qd = Vector2.new(bar_index + 100.0, 0.0)
//     new(_qa, _qb, _qc, _qd)

// }
// copy           () {

// @function Copy a existing quad object.
// @param this Quad . Source quad.
// @returns Quad.
export method copy (TDraw.Quad this) =>
    TDraw.Quad.copy(this)

// }
// delete			() {

// @function Delete all the underlying object properties (line, fill).
// @param this	`Quad`	Source triangle.
// @returns `void`.
export method delete (TDraw.Quad this) =>
	this.ab.delete()
	this.bc.delete()
	this.cd.delete()
    this.da.delete()
	this.fill.delete()

// }
//#endregion



//#region   -> Properties:

// set_position_a () {

// @function Set the position of corner `a` (modifies source quad).
// @param this Quad . Source quad.
// @param x    int      . Value at the x axis.
// @param y    float    . Value at the y axis.
// @returns Source Quad.
export method set_position_a (TDraw.Quad this, int x, float y) =>
    this.ab.set_xy1(x, y)
    this.da.set_xy2(x, y)
    this

// @function Set the position of corner `a` (modifies source quad).
// @param this     Quad . Source quad.
// @param position Vector2  . New position.
// @returns Source Quad.
export method set_position_a (TDraw.Quad this, TMath.Vector2 position) =>
    this.ab.set_xy1(int(position.x), position.y)
    this.da.set_xy2(int(position.x), position.y)
    this

// }
// set_position_b () {

// @function Set the position of corner `b` (modifies source quad).
// @param this Quad . Source quad.
// @param x    int      . Value at the x axis.
// @param y    float    . Value at the y axis.
// @returns Source Quad.
export method set_position_b (TDraw.Quad this, int x, float y) =>
    this.ab.set_xy2(x, y)
    this.bc.set_xy1(x, y)
    this

// @function Set the position of corner `b` (modifies source quad).
// @param this     Quad . Source quad.
// @param position Vector2  . New position.
// @returns Source Quad.
export method set_position_b (TDraw.Quad this, TMath.Vector2 position) =>
    this.ab.set_xy2(int(position.x), position.y)
    this.bc.set_xy1(int(position.x), position.y) 
    this

// }
// set_position_c () {

// @function Set the position of corner `c` (modifies source quad).
// @param this Quad . Source quad.
// @param x    int      . Value at the x axis.
// @param y    float    . Value at the y axis.
// @returns Source Quad.
export method set_position_c (TDraw.Quad this, int x, float y) =>
    this.bc.set_xy2(x, y)
    this.cd.set_xy2(x, y) // the origin/target are inverted because of the fill
    this

// @function Set the position of corner `c` (modifies source quad).
// @param this     Quad . Source quad.
// @param position Vector2  . New position.
// @returns Source Quad.
export method set_position_c (TDraw.Quad this, TMath.Vector2 position) =>
    this.bc.set_xy2(int(position.x), position.y)
    this.cd.set_xy2(int(position.x), position.y) // the origin/target are inverted because of the fill
    this

// }
// set_position_d () {

// @function Set the position of corner `d` (modifies source quad).
// @param this Quad  . Source quad.
// @param x    int   . Value at the x axis.
// @param y    float . Value at the y axis.
// @returns Source Quad.
export method set_position_d (TDraw.Quad this, int x, float y) =>
    this.cd.set_xy1(x, y) // the origin/target are inverted because of the fill
    this.da.set_xy1(x, y)
    this

// @function Set the position of corner `d` (modifies source quad).
// @param this     Quad    . Source quad.
// @param position Vector2 . New position.
// @returns Source Quad.
export method set_position_d (TDraw.Quad this, TMath.Vector2 position) =>
    this.cd.set_xy1(int(position.x), position.y) // the origin/target are inverted because of the fill
    this.da.set_xy1(int(position.x), position.y)
    this

// TEST: 20230220 RS
// if barstate.islast
//     _qa = Vector2.new(bar_index + 0.0, 0.0)
//     _qb = Vector2.new(bar_index + 0.0, 100.0)
//     _qc = Vector2.new(bar_index + 100.0, 100.0)
//     _qd = Vector2.new(bar_index + 100.0, 0.0)
//     _q = new(_qa, _qb, _qc, _qd)
//     _q.set_position_a(bar_index+10, 10.0)
//     _q.set_position_b(bar_index+110, 120.0)
//     _q.set_position_c(bar_index+210, 110.0)
//     _q.set_position_d(bar_index+210, 50.0)

// }
// set_line_style () {

// @function Update quad style options (modifies Source quad).
// @param this       Quad   . Source quad.
// @param bg_color   color  . Color of the background.
// @param line_color color  . Color of the line.
// @param line_style string . Style of the line.
// @param line_width int    . Width of the line.
// @returns Source Quad.
export method set_style (
 TDraw.Quad this                  ,
 color      bg_color   = #2196f3, 
 color      line_color = #2196f3, 
 string     line_style = 'sol'    , 
 int        line_width = 1        ) =>
    linefill.set_color(this.fill, bg_color)
    this.ab.set_color(line_color) , this.ab.set_width(line_width) , this.ab.set_style(line_style)
    this.bc.set_color(line_color) , this.bc.set_width(line_width) , this.bc.set_style(line_style)
    this.cd.set_color(line_color) , this.cd.set_width(line_width) , this.cd.set_style(line_style)
    this.da.set_color(line_color) , this.da.set_width(line_width) , this.da.set_style(line_style)
    this

// TEST: 20230218 RS
// qstyle = input.string('sol', options=[line.style_solid, line.style_dashed, line.style_dotted])
// qlinecol = input.color(#e3e3e3)
// qbgcol = input.color(#e3e3e3)
// qlinew = input.int(1)
// if barstate.islast
//     _qa = Vector2.new(bar_index + 0.0, 0.0)
//     _qb = Vector2.new(bar_index + 100.0, 50.0)
//     _qc = Vector2.new(bar_index + 200.0, 50.0)
//     _qd = Vector2.new(bar_index + 100.0, 0.0)
//     _q = new(_qa, _qb, _qc, _qd)
//     _q.set_style(qbgcol, qlinecol, qstyle, qlinew)

// }
// set_bg_color   () {

// @function Update quad style options (modifies Source quad).
// @param this     Quad  . Source quad.
// @param bg_color color . Color of the background.
// @returns Source Quad.
export method set_bg_color (
 TDraw.Quad this                  ,
 color      bg_color   = #2196f3) =>
    linefill.set_color(this.fill, bg_color)
    this

// }
// set_line_color () {

// @function Update quad style options (modifies Source quad).
// @param this       Quad  . Source quad.
// @param line_color color . Color of the line.
// @returns Source Quad.
export method set_line_color (
 TDraw.Quad this                  ,
 color      line_color = #2196f3) =>
    this.ab.set_color(line_color)
    this.bc.set_color(line_color)
    this.cd.set_color(line_color)
    this.da.set_color(line_color)
    this

// }
// set_line_style () {

// @function Update quad style options (modifies Source quad).
// @param this       Quad   . Source quad.
// @param line_style string . Style of the line.
// @returns Source Quad.
export method set_line_style (
 TDraw.Quad this                  ,
 string     line_style = 'sol'    ) =>
    this.ab.set_style(line_style)
    this.bc.set_style(line_style)
    this.cd.set_style(line_style)
    this.da.set_style(line_style)
    this

// }
// set_line_width () {

// @function Update quad style options (modifies Source quad).
// @param this       Quad . Source quad.
// @param line_width int      . Width of the line.
// @returns Source Quad.
export method set_line_width (
 TDraw.Quad this                  ,
 int        line_width = 1        ) =>
    this.ab.set_width(line_width)
    this.bc.set_width(line_width)
    this.cd.set_width(line_width)
    this.da.set_width(line_width)
    this

// }

//#endregion



//#region   -> Instance Methods:

// move           () {

// @function Move quad by provided amount (modifies source quad).
// @param this Quad  . Source quad.
// @param x    float . Amount to move the vertices of the quad in the x axis.
// @param y    float . Amount to move the vertices of the quad in the y axis.
// @returns Source Quad.
export method move (TDraw.Quad this, int x=0, float y=0.0) =>
    int _ax = this.ab.get_x1() , float _ay = this.ab.get_y1()
    int _bx = this.bc.get_x1() , float _by = this.bc.get_y1()
    int _cx = this.cd.get_x2() , float _cy = this.cd.get_y2() // the origin/target are inverted because of the fill
    int _dx = this.da.get_x1() , float _dy = this.da.get_y1()
    this.ab.set_xy1(_ax + x, _ay + y) , this.ab.set_xy2(_bx + x, _by + y)
    this.bc.set_xy1(_bx + x, _by + y) , this.bc.set_xy2(_cx + x, _cy + y)
    this.cd.set_xy2(_cx + x, _cy + y) , this.cd.set_xy1(_dx + x, _dy + y) // the origin/target are inverted because of the fill
    this.da.set_xy1(_dx + x, _dy + y) , this.da.set_xy2(_ax + x, _ay + y)
    this

// @function Move quad by provided amount (modifies source quad).
// @param this   Quad    . Source quad.
// @param amount Vector2 . Amount to move the vertices of the quad in the x and y axis.
// @returns Source Quad.
export method move (TDraw.Quad this, TMath.Vector2 amount) =>
    this.move(int(amount.x), amount.y)

// TEST: 20230218 RS
// mx = input.int(0, step=10)
// my = input.float(0.0, step=10.0)
// if barstate.islast
//     _qa = Vector2.new(bar_index + 0.0, 0.0)
//     _qb = Vector2.new(bar_index + 100.0, 50.0)
//     _qc = Vector2.new(bar_index + 200.0, 50.0)
//     _qd = Vector2.new(bar_index + 150.0, 20.0)
//     _q = new(_qa, _qb, _qc, _qd)
//     _q.move(mx, my)

// }
// rotate_around  () {

// @function Rotate source quad around a center (modifies source quad).
// @param this   Quad    . Source quad.
// @param center Vector2 . Center coordinates of the rotation.
// @param angle  float   . Value of angle in degrees.
// @returns Source Quad.
export method rotate_around (TDraw.Quad this, TMath.Vector2 center, float angle) =>
    int _ax = this.ab.get_x1() , float _ay = this.ab.get_y1()
    int _bx = this.bc.get_x1() , float _by = this.bc.get_y1()
    int _cx = this.cd.get_x2() , float _cy = this.cd.get_y2() // the origin/target are inverted because of the fill
    int _dx = this.cd.get_x1() , float _dy = this.cd.get_y1()
    _a = Vector2.new(_ax, _ay).rotate_around(center, angle)
    _b = Vector2.new(_bx, _by).rotate_around(center, angle)
    _c = Vector2.new(_cx, _cy).rotate_around(center, angle)
    _d = Vector2.new(_dx, _dy).rotate_around(center, angle)
    this.ab.set_xy1(int(_a.x), _a.y) , this.ab.set_xy2(int(_b.x), _b.y)
    this.bc.set_xy1(int(_b.x), _b.y) , this.bc.set_xy2(int(_c.x), _c.y)
    this.cd.set_xy2(int(_c.x), _c.y) , this.cd.set_xy1(int(_d.x), _d.y) // the origin/target are inverted because of the fill
    this.da.set_xy1(int(_d.x), _d.y) , this.da.set_xy2(int(_a.x), _a.y)
    this

// @function Rotate source quad around a center (modifies source quad).
// @param this     Quad  . Source quad.
// @param center_x int   . Center coordinates of the rotation.
// @param center_y float . Center coordinates of the rotation.
// @param angle    float . Value of angle in degrees.
// @returns Source Quad.
export method rotate_around (TDraw.Quad this, int center_x, float center_y, float angle) =>
    this.rotate_around(Vector2.new(center_x, center_y), angle)

// TEST: 20230218 RS
// mx = input.int(50, step=10)
// my = input.float(50.0, step=10.0)
// degree = input.float(0.0, step=10.0)
// if barstate.islast
//     _qa = Vector2.new(bar_index + 0.0, 0.0)
//     _qb = Vector2.new(bar_index + 100.0, 50.0)
//     _qc = Vector2.new(bar_index + 200.0, 50.0)
//     _qd = Vector2.new(bar_index + 150.0, 20.0)
//     _center = Vector2.new(bar_index + mx, my)
//     _q = new(_qa, _qb, _qc, _qd)
//     _q.rotate_around(_center, degree)

// }

//#endregion