package mdb

import (
	"context"
	_ "embed"

	"zombiezen.com/go/sqlite"
	"zombiezen.com/go/sqlite/sqlitex"

	"git.sunturtle.xyz/zephyr/horse"
)

var (
	//go:embed sql/character.sql
	characterSQL string
	//go:embed sql/affinity.sql
	affinitySQL string
	//go:embed sql/affinity-detail.sql
	affinityDetailSQL string
	//go:embed sql/uma.sql
	umaSQL string
	//go:embed sql/conversation.sql
	conversationSQL string
)

// Characters retrieves all named characters.
func Characters(ctx context.Context, db *sqlitex.Pool) ([]horse.Character, error) {
	return load(ctx, db, make([]horse.Character, 0, 128), characterSQL, func(s *sqlite.Stmt) horse.Character {
		return horse.Character{
			ID:   horse.CharacterID(s.ColumnInt(0)),
			Name: s.ColumnText(1),
		}
	})
}

// AffinitySummary gets precomputed base affinity for all pairs and trios of characters.
func AffinitySummary(ctx context.Context, db *sqlitex.Pool) ([]horse.AffinityRelation, error) {
	return load(ctx, db, nil, affinitySQL, func(s *sqlite.Stmt) horse.AffinityRelation {
		return horse.AffinityRelation{
			IDA:      horse.CharacterID(s.ColumnInt(0)),
			IDB:      horse.CharacterID(s.ColumnInt(1)),
			IDC:      horse.CharacterID(s.ColumnInt(2)),
			Affinity: s.ColumnInt(3),
		}
	})
}

// AffinityDetail gets all individual affinity group entries.
func AffinityDetail(ctx context.Context, db *sqlitex.Pool) ([]horse.AffinityDetail, error) {
	return load(ctx, db, nil, affinityDetailSQL, func(s *sqlite.Stmt) horse.AffinityDetail {
		return horse.AffinityDetail{
			CharaID:  horse.CharacterID(s.ColumnInt(0)),
			Relation: uint16(s.ColumnInt(1)),
			Affinity: uint16(s.ColumnInt(2)),
		}
	})
}

// Umas retrieves all trainable Uma variants.
func Umas(ctx context.Context, db *sqlitex.Pool) ([]horse.Uma, error) {
	return load(ctx, db, make([]horse.Uma, 0, 128), umaSQL, func(s *sqlite.Stmt) horse.Uma {
		return horse.Uma{
			ID:          horse.UmaID(s.ColumnInt(0)),
			CharacterID: horse.CharacterID(s.ColumnInt(1)),
			Name:        s.ColumnText(2),
			Variant:     s.ColumnText(3),
			Sprint:      horse.AptitudeLevel(s.ColumnInt(5)),
			Mile:        horse.AptitudeLevel(s.ColumnInt(6)),
			Medium:      horse.AptitudeLevel(s.ColumnInt(7)),
			Long:        horse.AptitudeLevel(s.ColumnInt(8)),
			Front:       horse.AptitudeLevel(s.ColumnInt(9)),
			Pace:        horse.AptitudeLevel(s.ColumnInt(10)),
			Late:        horse.AptitudeLevel(s.ColumnInt(11)),
			End:         horse.AptitudeLevel(s.ColumnInt(12)),
			Turf:        horse.AptitudeLevel(s.ColumnInt(13)),
			Dirt:        horse.AptitudeLevel(s.ColumnInt(14)),
			Unique:      horse.SkillID(s.ColumnInt(15)),
			Skill1:      horse.SkillID(s.ColumnInt(16)),
			Skill2:      horse.SkillID(s.ColumnInt(17)),
			Skill3:      horse.SkillID(s.ColumnInt(18)),
			SkillPL2:    horse.SkillID(s.ColumnInt(19)),
			SkillPL3:    horse.SkillID(s.ColumnInt(20)),
			SkillPL4:    horse.SkillID(s.ColumnInt(21)),
			SkillPL5:    horse.SkillID(s.ColumnInt(22)),
		}
	})
}

func Conversations(ctx context.Context, db *sqlitex.Pool) ([]horse.Conversation, error) {
	return load(ctx, db, make([]horse.Conversation, 0, 1024), conversationSQL, func(s *sqlite.Stmt) horse.Conversation {
		return horse.Conversation{
			CharacterID:   horse.CharacterID(s.ColumnInt(0)),
			Number:        s.ColumnInt(1),
			Location:      horse.LobbyConversationLocationID(s.ColumnInt(2)),
			Chara1:        horse.CharacterID(s.ColumnInt(3)),
			Chara2:        horse.CharacterID(s.ColumnInt(4)),
			Chara3:        horse.CharacterID(s.ColumnInt(5)),
			ConditionType: s.ColumnInt(6),
		}
	})
}
