package nodeshape

import (
	

	
)

// Table is basically a rectangle
type shapeTable struct {
	*shapeSquare

	numColumns int
}

// NumColumns returns the number of row-specific side ports for a table shape.
// Non-table shapes do not carry this metadata.
func ( Shape) int {
	,  := .(*shapeTable)
	if ! {
		return 0
	}
	return .numColumns
}

// SetNumColumns updates the row-specific side ports for a table shape.
// It is a no-op for every other shape.
func ( Shape,  int) {
	if ,  := .(*shapeTable);  {
		.numColumns = 
	}
}

// TablePortIndex returns the absolute snap-point index for a table column on
// the requested side. Non-table shapes and non-side orientations return
// ok=false so callers can use their generic port policy.
func ( Shape,  geo.Orientation,  int) ( int,  bool) {
	,  := .(*shapeTable)
	if ! {
		return 0, false
	}
	 := .numColumns
	if  == 0 {
		 = 1
	}
	if  < 0 ||  >=  {
		panic("table column port index out of range")
	}
	switch  {
	case geo.Left:
		return 3 + , true
	case geo.Right:
		return 6 +  + , true
	default:
		return 0, false
	}
}

// TableColumnPortValue returns the table column's concrete side port without
// materializing all of the shape's snap points. Non-table shapes and non-side
// orientations return ok=false so callers can use their generic port policy.
func ( Shape,  geo.Orientation,  int) ( geo.Point,  bool) {
	,  := .(*shapeTable)
	if ! || ( != geo.Left &&  != geo.Right) {
		return geo.Point{}, false
	}
	 := .numColumns
	if  == 0 {
		if  != 0 {
			panic("table column port index out of range")
		}
	} else if  < 0 ||  >=  {
		panic("table column port index out of range")
	}

	 := 0.5
	if  > 0 {
		 := 1. / (float64() + 1.)
		 :=  + /2.
		for range  {
			 += 
		}
		 = math.Round(*10_000) / 10_000
		 = geo.TruncateDecimals()
	}
	 := 0.0
	if  == geo.Right {
		 = 1.0
	}
	 := .GetBox()
	return geo.Point{
		X: .TopLeft.X + math.Round(.Width*),
		Y: .TopLeft.Y + math.Round(.Height*),
	}, true
}

// SnapPointPercentages returns relative port positions. Row ports exclude the
// table header and sit at each row's center.
// Below, `*` represents the ports.
// ┌──*────*────*──┐
// │  HEADER       │
// ├───────────────┤
// *  COLUMN 1     *
// ├───────────────┤
// *  COLUMN 2     *
// ├───────────────┤
// *  COLUMN 3     *
// └──*────*────*──┘
func ( shapeTable) () [][]*geo.RelativePoint {
	var ,  []*geo.RelativePoint
	if .numColumns == 0 {
		 = []*geo.RelativePoint{geo.NewRelativePoint(0., 0.5)}
		 = []*geo.RelativePoint{geo.NewRelativePoint(1., 0.5)}
	} else {
		 = make([]*geo.RelativePoint, 0, .numColumns+1)
		 = make([]*geo.RelativePoint, 0, .numColumns+1)
		// *row* is used here instead of *column* because during rendering of this shape, columns are drawn in rows
		 := 1. / (float64(.numColumns) + 1.) // +1 because of the table header
		 :=  / 2.
		// start in rowHeightPercentage + midRowPercentage to skip the header
		for  :=  + ;  < 1.;  +=  {
			 := math.Round(*10_000) / 10_000 // clips decimal places to avoid numerical issues
			 = append(, geo.NewRelativePoint(0., ))
			 = append(, geo.NewRelativePoint(1., ))
		}
	}
	return [][]*geo.RelativePoint{
		// Top
		{
			geo.NewRelativePoint(0.25, 0),
			geo.NewRelativePoint(0.5, 0),
			geo.NewRelativePoint(0.75, 0),
		},
		,
		// Bottom
		{
			geo.NewRelativePoint(0.25, 1),
			geo.NewRelativePoint(0.5, 1),
			geo.NewRelativePoint(0.75, 1),
		},
		,
	}
}

func ( shapeTable) () []int {
	if .numColumns > 0 {
		return nil
	}
	return []int{
		1,
		3,
		5,
		7,
	}
}

func ( shapeTable) ( geo.Orientation) int {
	if .numColumns > 0 {
		return -1
	}
	 := .CenterPortIndices()
	var  int
	switch  {
	case geo.Top:
		 = 0
	case geo.Left:
		 = 1
	case geo.Bottom:
		 = 2
	case geo.Right:
		 = 3
	default:
		return -1
	}

	return []
}

func ( shapeTable) () map[int]int {
	if .numColumns > 0 {
		return nil
	}
	 := .CenterPortIndices()
	return map[int]int{
		// Top and bottom
		[0]: [2],
		[2]: [0],
		// Left and right
		[1]: [3],
		[3]: [1],
	}
}

func ( shapeTable) ( geo.Orientation) []int {
	 := .numColumns
	if  == 0 {
		// in this case, make the side ports for the table header
		 = 1
	}
	 := []int{0, 1, 2}

	 := [2] + 1
	 := make([]int, )
	for  := 0;  < ; ++ {
		[] =  + 
	}

	 := [-1] + 1
	 := make([]int, 3)
	for  := 0;  < 3; ++ {
		[] =  + 
	}

	 := [2] + 1
	 := make([]int, )
	for  := 0;  < ; ++ {
		[] =  + 
	}

	switch  {
	case geo.Top:
		return 
	case geo.Left:
		return 
	case geo.Bottom:
		return 
	case geo.Right:
		return 
	case geo.TopLeft:
		return append(, ...)
	case geo.TopRight:
		return append(, ...)
	case geo.BottomLeft:
		return append(, ...)
	case geo.BottomRight:
		return append(, ...)
	default:
		return []int{}
	}
}