package d2grid

import (
	

	
	
)

type gridDiagram struct {
	root    *d2graph.Object
	objects []*d2graph.Object
	edges   []*d2graph.Edge
	rows    int
	columns int

	// if true, place objects left to right along rows
	// if false, place objects top to bottom along columns
	rowDirected bool

	width  float64
	height float64

	verticalGap   int
	horizontalGap int
}

func newGridDiagram( *d2graph.Object) *gridDiagram {
	 := gridDiagram{
		root:          ,
		objects:       .ChildrenArray,
		verticalGap:   DEFAULT_GAP,
		horizontalGap: DEFAULT_GAP,
	}

	if .GridRows != nil {
		.rows, _ = strconv.Atoi(.GridRows.Value)
	}
	if .GridColumns != nil {
		.columns, _ = strconv.Atoi(.GridColumns.Value)
	}

	if .rows != 0 && .columns != 0 {
		// . row-directed  column-directed
		// .  ┌───────┐    ┌───────┐
		// .  │ a b c │    │ a d g │
		// .  │ d e f │    │ b e h │
		// .  │ g h i │    │ c f i │
		// .  └───────┘    └───────┘
		// if keyword rows is first, make it row-directed, if columns is first it is column-directed
		if .GridRows.MapKey.Range.Before(.GridColumns.MapKey.Range) {
			.rowDirected = true
		}

		// rows and columns specified, but we want to continue naturally if user enters more objects
		// e.g. 2 rows, 3 columns specified + g added:      │ with 3 columns, 2 rows:
		// . original  add row   add column                 │ original  add row   add column
		// . ┌───────┐ ┌───────┐ ┌─────────┐                │ ┌───────┐ ┌───────┐ ┌─────────┐
		// . │ a b c │ │ a b c │ │ a b c d │                │ │ a c e │ │ a d g │ │ a c e g │
		// . │ d e f │ │ d e f │ │ e f g   │                │ │ b d f │ │ b e   │ │ b d f   │
		// . └───────┘ │ g     │ └─────────┘                │ └───────┘ │ c f   │ └─────────┘
		// .           └───────┘ ▲                          │           └───────┘ ▲
		// .           ▲         └─existing objects modified│           ▲         └─existing columns preserved
		// .           └─existing rows preserved            │           └─existing objects modified
		 := .rows * .columns
		for  < len(.objects) {
			if .rowDirected {
				.rows++
				 += .columns
			} else {
				.columns++
				 += .rows
			}
		}
	} else if .columns == 0 {
		.rowDirected = true
		// we can only make N rows with N objects
		if len(.objects) < .rows {
			.rows = len(.objects)
		}
	} else {
		if len(.objects) < .columns {
			.columns = len(.objects)
		}
	}

	// grid gap sets both, but can be overridden
	if .GridGap != nil {
		.verticalGap, _ = strconv.Atoi(.GridGap.Value)
		.horizontalGap = .verticalGap
	}
	if .VerticalGap != nil {
		.verticalGap, _ = strconv.Atoi(.VerticalGap.Value)
	}
	if .HorizontalGap != nil {
		.horizontalGap, _ = strconv.Atoi(.HorizontalGap.Value)
	}

	for ,  := range .objects {
		.TopLeft = geo.NewPoint(0, 0)
	}

	return &
}

func ( *gridDiagram) (,  float64) {
	for ,  := range .objects {
		.MoveWithDescendants(, )
	}
	for ,  := range .edges {
		.Move(, )
	}
}