package engine

// Grid represents a 4x4 layout grid for positioning shapes in a jdenticon
type Grid struct {
	Size    float64
	Cell    int
	X       int
	Y       int
	Padding int
}

// Position represents an x, y coordinate pair
type Position struct {
	X, Y int
}

// NewGrid creates a new Grid with the specified icon size and padding ratio
func NewGrid(iconSize float64, paddingRatio float64) *Grid {
	// Calculate padding and round to nearest integer (matches JS: (0.5 + size * parsedConfig.iconPadding) | 0)
	padding := int(0.5 + iconSize*paddingRatio)
	size := iconSize - float64(padding*2)
	
	// Calculate cell size and ensure it is an integer (matches JS: 0 | (size / 4))
	cell := int(size / 4)
	
	// Center the icon since cell size is integer-based (matches JS implementation)
	// Since the cell size is integer based, the actual icon will be slightly smaller than specified => center icon
	x := padding + int((size - float64(cell*4))/2)
	y := padding + int((size - float64(cell*4))/2)
	
	return &Grid{
		Size:    size,
		Cell:    cell,
		X:       x,
		Y:       y,
		Padding: padding,
	}
}

// CellToCoordinate converts a grid cell position to actual coordinates
func (g *Grid) CellToCoordinate(cellX, cellY int) (x, y float64) {
	return float64(g.X + cellX*g.Cell), float64(g.Y + cellY*g.Cell)
}

// GetCellSize returns the size of each cell in the grid
func (g *Grid) GetCellSize() float64 {
	return float64(g.Cell)
}

// LayoutEngine manages the overall layout and positioning of icon elements
type LayoutEngine struct {
	grid *Grid
}

// NewLayoutEngine creates a new LayoutEngine with the specified parameters
func NewLayoutEngine(iconSize float64, paddingRatio float64) *LayoutEngine {
	return &LayoutEngine{
		grid: NewGrid(iconSize, paddingRatio),
	}
}

// Grid returns the underlying grid
func (le *LayoutEngine) Grid() *Grid {
	return le.grid
}

// GetShapePositions returns the positions for different shape types based on the jdenticon pattern
func (le *LayoutEngine) GetShapePositions(shapeType string) []Position {
	switch shapeType {
	case "sides":
		// Sides: positions around the perimeter (8 positions)
		return []Position{
			{1, 0}, {2, 0}, {2, 3}, {1, 3}, // top and bottom
			{0, 1}, {3, 1}, {3, 2}, {0, 2}, // left and right
		}
	case "corners":
		// Corners: four corner positions
		return []Position{
			{0, 0}, {3, 0}, {3, 3}, {0, 3},
		}
	case "center":
		// Center: four center positions
		return []Position{
			{1, 1}, {2, 1}, {2, 2}, {1, 2},
		}
	default:
		return []Position{}
	}
}

// ApplySymmetry applies symmetrical transformations to position indices
// This ensures the icon has the characteristic jdenticon symmetry
func ApplySymmetry(positions []Position, index int) []Position {
	if index >= len(positions) {
		return positions
	}
	
	// For jdenticon, we apply rotational symmetry
	// The pattern is designed to be symmetrical, so we don't need to modify positions
	// The symmetry is achieved through the predefined position arrays
	return positions
}

// GetTransformedPosition applies rotation and returns the final position
func (le *LayoutEngine) GetTransformedPosition(cellX, cellY int, rotation int) (x, y float64, cellSize float64) {
	// Apply rotation if needed (rotation is 0-3 for 0°, 90°, 180°, 270°)
	switch rotation % 4 {
	case 0: // 0°
		// No rotation
	case 1: // 90° clockwise
		cellX, cellY = cellY, 3-cellX
	case 2: // 180°
		cellX, cellY = 3-cellX, 3-cellY
	case 3: // 270° clockwise (90° counter-clockwise)
		cellX, cellY = 3-cellY, cellX
	}
	
	x, y = le.grid.CellToCoordinate(cellX, cellY)
	cellSize = le.grid.GetCellSize()
	return
}

// ValidateGrid checks if the grid configuration is valid
func (g *Grid) ValidateGrid() bool {
	return g.Cell > 0 && g.Size > 0 && g.Padding >= 0
}

// GetIconBounds returns the bounds of the icon within the grid
func (g *Grid) GetIconBounds() (x, y, width, height float64) {
	return float64(g.X), float64(g.Y), float64(g.Cell * 4), float64(g.Cell * 4)
}

// GetCenterOffset returns the offset needed to center content within a cell
func (g *Grid) GetCenterOffset() (dx, dy float64) {
	return float64(g.Cell) / 2, float64(g.Cell) / 2
}