package gamemap

import (
	"fmt"

	"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
	"lab.zaar.be/thefish/alchemyst-go/engine/types"
	"lab.zaar.be/thefish/alchemyst-go/util/appctx"
)

//fixme move to config
var mapWidth = 150
var mapHeight = 90


type Level struct {
	types.Rect
	Name    string
	Branch  string
	Depth   int
	Objects *[]ecs.Entity
	Tiles   []*Tile
}

func (l *Level) GetTile (coords types.Coords) *Tile {
	return l.Tiles[coords.Y*l.W+coords.X]
}

func (l *Level) GetTileNbs (coords types.Coords) []*Tile {
	result := make([]*Tile,0)
	for i := coords.X-1; i < coords.X+1; i++ {
		for j := coords.Y-1; j < coords.Y+1; j++ {
			nbc := types.Coords{X: i,Y: j}
			if l.InBounds(nbc){
				if nbc == coords {
					continue
				}
				result = append(result, l.GetTileByXY(i,j))
			}
		}
	}
	return result
}

func (l *Level) GetTileByXY (x,y int) *Tile {
	return l.Tiles[y*l.W+x]
}

func (l *Level) SetTile (coords types.Coords, tile *Tile) {
	l.Tiles[coords.Y*l.W+coords.X] = tile
}

func (l *Level) SetTileByXY (x,y int, tile *Tile) {
	l.Tiles[y*l.W+x] = tile
}

//only replaces tile if original is not passable
func (l *Level) MakePassByXY (x,y int, tile *Tile) {
	t := l.Tiles[y*l.W+x]
	if t.BlocksPass {
		l.Tiles[y*l.W+x] = tile
	}
}


func (l *Level) Put (x, y int, tileFunc interface{}) {
	tile := tileFunc.(func() *Tile)()
	if tile == nil {
		appctx.Logger().Fatal().Msgf("Got non-tile type to put into level: %v", tile)
	}
	if l.InBounds(types.Coords{X: x, Y: y}) {
		l.Tiles[y*l.W+x] = tile
	}
}

func NewLevel(branch string, depth int) *Level {
	l := &Level{
		Name:     fmt.Sprintf(branch, depth),
		Depth:    depth,
		Rect: types.NewRect(0,0, mapWidth, mapHeight),
	}

	l.Tiles = make([]*Tile, l.W*l.H)
	appctx.Logger().Debug().Msgf("Generating level of branch %s depth %d", branch, depth)
	return l
}

func (l *Level) SetAllInvisible() {
	for idx := range l.Tiles {
		l.Tiles[idx].Visible = false
	}
}

func (l *Level) SetAllVisible() {
	for idx := range l.Tiles {
		l.Tiles[idx].Visible = true
	}
}
