package tetromino

import "tetris/internal/types"

// TetrominoShapes defines the shape of each tetromino type
var TetrominoShapes = map[types.BlockType][][]bool{
	types.IBlock: {
		{false, false, false, false},
		{false, false, false, false},
		{true, true, true, true},
		{false, false, false, false},
	},
	types.JBlock: {
		{true, false, false},
		{true, true, true},
		{false, false, false},
	},
	types.LBlock: {
		{false, false, true},
		{true, true, true},
		{false, false, false},
	},
	types.OBlock: {
		{true, true},
		{true, true},
	},
	types.SBlock: {
		{false, true, true},
		{true, true, false},
		{false, false, false},
	},
	types.TBlock: {
		{false, true, false},
		{true, true, true},
		{false, false, false},
	},
	types.ZBlock: {
		{true, true, false},
		{false, true, true},
		{false, false, false},
	},
}

// Rotation offsets for I piece wall kicks
var IKicks = [][2]int{
	{0, 0},
	{-2, 0},
	{1, 0},
	{-2, -1},
	{1, 2},
}

// Rotation offsets for other pieces wall kicks
var NormalKicks = [][2]int{
	{0, 0},
	{-1, 0},
	{1, 0},
	{0, -1},
}

// Tetromino represents a complete tetris piece
type Tetromino struct {
	Blocks    []types.Block
	BlockType types.BlockType
	X, Y      int
}

// New creates a new tetromino of the specified type
func New(blockType types.BlockType, x, y int) *Tetromino {
	shape := TetrominoShapes[blockType]
	blocks := make([]types.Block, 0)

	for i := range shape {
		for j := range shape[i] {
			if shape[i][j] {
				blocks = append(blocks, types.Block{
					X:    j,
					Y:    i,
					Type: blockType,
				})
			}
		}
	}

	// Adjust initial position for I piece
	if blockType == types.IBlock {
		y-- // Start one row higher
	}

	return &Tetromino{
		Blocks:    blocks,
		BlockType: blockType,
		X:         x,
		Y:         y,
	}
}

// Move moves the tetromino by the specified delta
func (t *Tetromino) Move(dx, dy int) {
	t.X += dx
	t.Y += dy
}

// Rotate rotates the tetromino clockwise
func (t *Tetromino) Rotate() {
	if t.BlockType == types.OBlock {
		return // O block doesn't need rotation
	}

	// Get the size of the shape matrix
	size := 3
	if t.BlockType == types.IBlock {
		size = 4
	}

	// Create a temporary matrix for rotation
	matrix := make([][]bool, size)
	for i := range matrix {
		matrix[i] = make([]bool, size)
	}

	// Fill the matrix with current block positions
	for _, block := range t.Blocks {
		if block.Y >= 0 && block.Y < size && block.X >= 0 && block.X < size {
			matrix[block.Y][block.X] = true
		}
	}

	// Create a new rotated shape
	newBlocks := make([]types.Block, 0)

	// Perform rotation
	for y := 0; y < size; y++ {
		for x := 0; x < size; x++ {
			if matrix[y][x] {
				// Rotate coordinates 90 degrees clockwise
				newX := size - 1 - y
				newY := x
				newBlocks = append(newBlocks, types.Block{
					X:    newX,
					Y:    newY,
					Type: t.BlockType,
				})
			}
		}
	}

	t.Blocks = newBlocks
}

// GetAbsolutePositions returns the absolute positions of all blocks in the tetromino
func (t *Tetromino) GetAbsolutePositions() [][2]int {
	positions := make([][2]int, len(t.Blocks))
	for i, block := range t.Blocks {
		positions[i] = [2]int{t.X + block.X, t.Y + block.Y}
	}
	return positions
}
