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

//@version=5

// @description A helper library to make it simpler to create tables in pinescript
library("TableBuilder",overlay = true)

export type CellStyle
	color text_color
	string text_halign
	string text_valign
	int text_size
	color bgcolor
	string tooltip
	string text_font_family

export type TableStyle
	color bgcolor
	color frame_color
	int frame_width
	color border_color
	int border_width
	CellStyle default_cell_style

export type Cell
	table ref
	int column
	int row

export type Row
	table ref
	int row
	array<Cell> cells

export type Table
	table body
	array<Row> rows

export DefaultDarkStyle() =>
	style = TableStyle.new()
	style.bgcolor := color.rgb(15, 16, 46, 61)
	style.border_color :=color.rgb(0, 0, 0, 38)
	style.border_width := 1
	style.frame_color :=color.rgb(0, 0, 0, 38)
	style.frame_width := 3
	style	

// Cell Methods

// @function Change the size (width, height) of the table cell.
// @returns Cell
export method Size(Cell this,int width,int height) =>
	table.cell_set_width(table_id = this.ref,column = this.column, row = this.row,width = width)
	table.cell_set_height(table_id = this.ref,column = this.column, row = this.row,height = height)
	this

// @function Change the width of the table cell.
// @returns Cell
export method Width(Cell this,int width) =>
	table.cell_set_width(table_id = this.ref,column = this.column, row = this.row,width = width)
	this

// @function Change the height of the table cell.
// @returns Cell
export method Height(Cell this,int height) =>
	table.cell_set_height(table_id = this.ref,column = this.column, row = this.row,height = height)
	this

// @function Change the text of the table cell.
// @returns Cell
export method Text(Cell this,string text_) =>
	table.cell_set_text(table_id = this.ref,column = this.column,row = this.row,text = text_)
	this

// @function Change the text size of the table cell.
// @returns Cell
export method TextSize(Cell this,string text_size) =>
	table.cell_set_text_size(table_id = this.ref,column = this.column,row = this.row,text_size = text_size)
	this

// @function Change the text color of the table cell.
// @returns Cell
export method TextColor(Cell this,color c) =>
	table.cell_set_text_color(table_id = this.ref,column = this.column,row = this.row,text_color = c)
	this

// @function Change the background color of the table cell.
// @returns Cell
export method Bg(Cell this,color c) =>
	table.cell_set_bgcolor(table_id = this.ref,column = this.column,row = this.row,bgcolor = c)
	this

// @function Change the font family of the table cell.
// @returns Cell
export method Font(Cell this,string text_font_family) =>
	table.cell_set_text_font_family(this.ref,this.column,this.row,text_font_family)
	this

// @function Change the horizontal align of the table cell.
// @returns Cell
export method AlignH(Cell this,string halign) =>
	table.cell_set_text_halign(this.ref,this.column,this.row,halign)
	this

// @function Change the vertical align of the table cell.
// @returns Cell
export method AlignV(Cell this,string valign) =>
	table.cell_set_text_valign(this.ref,this.column,this.row,valign)
	this


// === Row Methods === 
// @function Get the cell corresponding to the column number
// @param column 
// @returns Cell
export method C(Row this,int column) =>
	this.cells.get(column)

// @function Set text
// @param c0 ... c29 
// @returns Row
export method Text(Row this,string c0=na,string c1=na,string c3=na,string c4=na,string c5=na,string c6=na,string c7=na,string c8=na,string c9=na,string c10=na,string c11=na,string c12=na,string c13=na,string c14=na,string c15=na,string c16=na,string c17=na,string c18=na,string c19=na,string c20=na,string c21=na,string c22=na,string c23=na,string c24=na,string c25=na,string c26=na,string c27=na,string c28=na,string c29=na) =>
	args = array.from(c0,c1,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26,c27,c28,c29)
	for c = 0 to math.min(args.size(),this.cells.size())-1 by 1
		this.C(c).Text(args.get(c))
	this

// @function Change the horizontal align of all cells in that row
// @returns Cell
export method AlignH(Row this,string halign) =>
	for c = 0 to this.cells.size()-1 by 1
		table.cell_set_text_halign(this.ref,c,this.row,halign)
	this

// @function Change the vertical of all cells in that row
// @returns Cell
export method AlignV(Row this,string valign) =>
	for c = 0 to this.cells.size()-1 by 1
		table.cell_set_text_valign(this.ref,c,this.row,valign)
	this

// @function Change the width of all cells in that row
// @returns Row
export method Font(Row this,string text_font_family) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).Font(text_font_family)
	this

// @function Change the width of all cells in that row
// @returns Row
export method Size(Row this,int width,int height) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).Size(width,height)
	this

// @function Change the width of all cells in that row
// @returns Row
export method Width(Row this,int width) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).Width(width)
	this

// @function Change the height of all cells in that row
// @returns Row
export method Height(Row this,int height) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).Height(height)
	this

// @function Change the text color of all cells in that row
// @returns Row
export method TextColor(Row this,color text_color) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).TextColor(text_color)
	this

// @function Set text size
// @returns Row
export method TextSize(Row this,string text_size) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).TextSize(text_size)
	this

// @function Change the background color of all cells in that row
// @returns Row
export method Bg(Row this,color bg) =>
	for c = 0 to this.cells.size()-1 by 1
		this.C(c).Bg(bg)
	this


// === Table Methods ===
export method C(Table this,int column,int row)=>
	this.rows.get(row).C(column)

export method R(Table this,int row)=>
	this.rows.get(row)

export method Style(Table this,TableStyle style)=>
	table.set_bgcolor(this.body,style.bgcolor)
	table.set_border_color(this.body,style.border_color)
	table.set_frame_color(this.body,style.frame_color)
	table.set_frame_width(this.body,style.frame_width)
	table.set_border_width(this.body,style.border_width)
	this

export method Position(Table this,string position)=>
	table.set_position(this.body,position)
	this

export new(string position,int columns,int rows,TableStyle style = na)=>
	body = table.new(position,columns,rows)
	_rows = array.new<Row>(rows)
	for r = 0 to rows-1 by 1
		_columns = array.new<Cell>(columns)
		for c = 0 to columns-1 by 1
			_columns.set(c,Cell.new(body,c,r))
		_rows.set(r,Row.new(body,r,_columns))
		
	tb = Table.new(body,_rows)
	tb.Style(na(style) ? DefaultDarkStyle() : style)
	tb

//  Example Code
var tbb = new(position.middle_center,3,5)
if barstate.isconfirmed
	header = tbb.R(0).TextColor(color.red).TextSize(size.large).Font(font.family_monospace)
	header.Text("Header 0","Header 2","Header 3")
	tbb.R(1).TextColor(color.white).TextSize(size.normal).Text("A","B","C").Bg(color.rgb(255, 255, 255, 74))
	tbb.R(2).TextColor(color.white).TextSize(size.normal).Text("A","B","C")
	tbb.R(3).TextColor(color.white).TextSize(size.normal).Text("A","B","C").Bg(color.rgb(255, 255, 255, 74))
	tbb.R(4).TextColor(color.white).TextSize(size.normal).Text("A","B","C")
