package entities

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/go-gl/mathgl/mgl64"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)

const (
	TileSize = 32.0 // Varje block ar 32x32 world units
)

type World struct {
	Width, Height, Depth int
	Grid                 [][][]Entity
	PortalTrigger        string // Håller reda på om vi ska byta rum
}

func NewWorld(w, h, d int) *World {
	grid := make([][][]Entity, w)
	for x := 0; x < w; x++ {
		grid[x] = make([][]Entity, h)
		for y := 0; y < h; y++ {
			grid[x][y] = make([]Entity, d)
		}
	}
	return &World{Width: w, Height: h, Depth: d, Grid: grid, PortalTrigger: ""}
}

func (w *World) GetEntityAt(x, y, z int) Entity {
	if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
		return nil
	}
	return w.Grid[x][y][z]
}

func (w *World) SetEntityAt(x, y, z int, e Entity) {
	if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
		return
	}
	w.Grid[x][y][z] = e
	if e != nil {
		e.SetPos(mgl64.Vec3{float64(x), float64(y), float64(z)})
	}
}

// Convert absolute 3D position to Grid index
func ToGridIndex(pos mgl64.Vec3) (int, int, int) {
	return int(pos[0]/TileSize), int(pos[1]/TileSize), int(pos[2]/TileSize)
}

type TiledLayer struct {
	Data   []int  `json:"data"`
	Height int    `json:"height"`
	Name   string `json:"name"`
	Width  int    `json:"width"`
	Type   string `json:"type"`
}

type TiledMap struct {
	Height int          `json:"height"`
	Width  int          `json:"width"`
	Layers []TiledLayer `json:"layers"`
}

type Portal struct {
	pos       mgl64.Vec3
	TargetMap string
}
func (p *Portal) Pos() mgl64.Vec3       { return p.pos }
func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos }
func (p *Portal) IsBlocking() bool      { return false }
func (p *Portal) IsMovable() bool       { return false }
func (p *Portal) Move(dx, dy, dz float64) {}
func (p *Portal) Damage(amount int)     {}
func (p *Portal) Pickup() bool          { return false }
func (p *Portal) GetHealth() int        { return 100 }
func (p *Portal) DrawSide(screen interface{}, x, y float64) {}
func (p *Portal) DrawTop(screen interface{}, x, y float64)  {}

// Ladda en värld från Tiled Export (.tmj)
func LoadWorldFromTiled(tmjPath string) (*World, error) {
	fileData, err := os.ReadFile(tmjPath)
	if err != nil {
		return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err)
	}

	var tMap TiledMap
	if err := json.Unmarshal(fileData, &tMap); err != nil {
		return nil, err
	}

	w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json
	
	tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png") 
	tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png") 
	tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png")

	for _, layer := range tMap.Layers {
		if layer.Type != "tilelayer" {
			continue
		}
		
		var yLevel int
		fmt.Sscanf(layer.Name, "Y%d", &yLevel)
		if yLevel < 0 || yLevel >= 10 {
			continue
		}

		for i, tileID := range layer.Data {
			if tileID == 0 {
				continue
			}
			x := i % layer.Width
			z := i / layer.Width

			var ent Entity

			if tileID == 3 { // Portal ID 
				target := "room2"
				if tmjPath == "mapp-maker/room2.tmj" {
					target = "room1"
				}
				ent = &Portal{ TargetMap: target }
			} else {
				// Mark 
				if yLevel < 9 { 
					ent = &Tile{ SideImg: tile12, TopImg: tile12 } 
				} else {
					ent = &Tile{ SideImg: tile02, TopImg: tile31 }
				}
			}

			w.SetEntityAt(x, yLevel, z, ent)
		}
	}

	return w, nil
}package entities

import (
"encoding/json"
"fmt"
"log"
"os"

"github.com/go-gl/mathgl/mgl64"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)

const (
TileSize = 32.0 // Varje block ar 32x32 world units
)

type World struct {
Width, Height, Depth int
Grid                 [][][]Entity
PortalTrigger        string // Håller reda på om vi ska byta rum
}

func NewWorld(w, h, d int) *World {
grid := make([][][]Entity, w)
for x := 0; x < w; x++ {
grid[x] = make([][]Entity, h)
for y := 0; y < h; y++ {
grid[x][y] = make([]Entity, d)
}
}
return &World{Width: w, Height: h, Depth: d, Grid: grid, PortalTrigger: ""}
}

func (w *World) GetEntityAt(x, y, z int) Entity {
if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
return nil
}
return w.Grid[x][y][z]
}

func (w *World) SetEntityAt(x, y, z int, e Entity) {
if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
return
}
w.Grid[x][y][z] = e
if e != nil {
e.SetPos(mgl64.Vec3{float64(x), float64(y), float64(z)})
}
}

// Convert absolute 3D position to Grid index
func ToGridIndex(pos mgl64.Vec3) (int, int, int) {
return int(pos[0]), int(pos[1]), int(pos[2])
}

type TiledLayer struct {
Data   []int  `json:"data"`
Height int    `json:"height"`
Name   string `json:"name"`
Width  int    `json:"width"`
Type   string `json:"type"`
}

type TiledMap struct {
Height int          `json:"height"`
Width  int          `json:"width"`
Layers []TiledLayer `json:"layers"`
}

type Portal struct {
pos       mgl64.Vec3
TargetMap string
}
func (p *Portal) Pos() mgl64.Vec3       { return p.pos }
func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos }
func (p *Portal) IsBlocking() bool      { return false }
func (p *Portal) IsMovable() bool       { return false }
func (p *Portal) Move(dx, dy, dz float64) {}
func (p *Portal) Damage(amount int)     {}
func (p *Portal) Pickup() bool          { return false }
func (p *Portal) GetHealth() int        { return 100 }
func (p *Portal) DrawSide(screen interface{}, x, y float64) {}
func (p *Portal) DrawTop(screen interface{}, x, y float64)  {}

// Ladda en värld från Tiled Export (.tmj)
func LoadWorldFromTiled(tmjPath string) (*World, error) {
fileData, err := os.ReadFile(tmjPath)
if err != nil {
return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err)
}

var tMap TiledMap
if err := json.Unmarshal(fileData, &tMap); err != nil {
return nil, err
}

w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json

tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png") 
tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png") 
tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png")

for _, layer := range tMap.Layers {
if layer.Type != "tilelayer" {
continue
}

var yLevel int
fmt.Sscanf(layer.Name, "Y%d", &yLevel)
if yLevel < 0 || yLevel >= 10 {
continue
}

for i, tileID := range layer.Data {
if tileID == 0 {
continue
}
x := i % layer.Width
z := i / layer.Width

var ent Entity

if tileID == 3 { // Portal ID 
log.Println("Hittade portal vid", x, yLevel, z)
target := "room2"
if tmjPath == "mapp-maker/room2.tmj" {
target = "room1"
}
ent = &Portal{ TargetMap: target }
} else {
// Mark 
if yLevel < 9 { 
ent = &Tile{ SideImg: tile12, TopImg: tile12 } 
} else {
ent = &Tile{ SideImg: tile02, TopImg: tile31 }
}
}

w.SetEntityAt(x, yLevel, z, ent)
}
}

return w, nil
}
