package maps

import (
	"image/color"

	"github.com/atridad/LilGuy/internal/portal"
	"github.com/atridad/LilGuy/internal/world"
	"github.com/hajimehoshi/ebiten/v2"
)

type LightSource struct {
	X, Y           float64
	Radius         float64
	Color          color.RGBA
	Intensity      float64
	ShadowDarkness float64
}

type LightConfig struct {
	AmbientBrightness float64
	Sources           []LightSource
}

type Map struct {
	ID              string
	Number          int
	DisplayName     string
	Width           float64
	Height          float64
	World           *world.World
	Portals         []*portal.Portal
	BackgroundColor color.NRGBA
	Lighting        LightConfig

	bakedImage *ebiten.Image
}

func NewMap(id string, number int, displayName string, width, height float64) *Map {
	return &Map{
		ID:              id,
		Number:          number,
		DisplayName:     displayName,
		Width:           width,
		Height:          height,
		World:           world.NewWorld(),
		Portals:         make([]*portal.Portal, 0),
		BackgroundColor: color.NRGBA{R: 135, G: 206, B: 235, A: 255},
		Lighting: LightConfig{
			AmbientBrightness: 1.0,
			Sources:           []LightSource{},
		},
	}
}

func (m *Map) AddPortal(p *portal.Portal) {
	m.Portals = append(m.Portals, p)
}

func (m *Map) GetPortalByID(id string) *portal.Portal {
	for _, p := range m.Portals {
		if p.ID == id {
			return p
		}
	}
	return nil
}

// Renders the static world geometry to an offscreen image
func (m *Map) Bake() {
	if m.Width <= 0 || m.Height <= 0 {
		return
	}
	m.bakedImage = ebiten.NewImage(int(m.Width), int(m.Height))
	m.bakedImage.Fill(m.BackgroundColor)
	m.World.Draw(m.bakedImage)
}

func (m *Map) Draw(screen *ebiten.Image) {
	if m.bakedImage != nil {
		screen.DrawImage(m.bakedImage, nil)
	} else {
		screen.Fill(m.BackgroundColor)
		m.World.Draw(screen)
	}

	// Draw portals
	for _, p := range m.Portals {
		p.Draw(screen)
	}
}

// Resets the map state
func (m *Map) Reset() {
	for _, p := range m.Portals {
		p.Enabled = true
		p.Visible = true
	}
}

func CreateDefaultMaps(screenWidth, screenHeight float64) (*Map, *Map) {
	plains := CreatePlains(screenWidth, screenHeight)
	desert := CreateDesert(screenWidth, screenHeight)
	return plains, desert
}
