package core

import "core:strings"
import "core:fmt"

CHARACTER_TEMPLATE_STRING :: "{age}-year-old {gender}, {hairColor} {hairStyle} hair, {eyeColor} eyes, {skinTone} skin, {bodyType} build, wearing {outfit}, {accessories}, {distinguishingFeatures}"

extract_age :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	// Try digit patterns first
	i: int = 0
	for i < len(lower)-3 {
		if lower[i] >= '0' && lower[i] <= '9' {
			start := i
			for i < len(lower) && lower[i] >= '0' && lower[i] <= '9' {
				i += 1
			}
			rest := lower[i:]
			if strings.has_prefix(rest, "-year-old") || strings.has_prefix(rest, "-year") || strings.has_prefix(rest, " years") || strings.has_prefix(rest, " year") {
				return strings.clone(lower[start:i])
			}
		}
		i += 1
	}

	// Try word patterns
	word_ages := []string{"young", "teen", "adult", "middle-aged", "middle aged", "elderly", "old"}
	for wa in word_ages {
		if strings.contains(lower, wa) {
			return strings.clone(wa)
		}
	}

	return ""
}

extract_gender :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	male_terms := []string{"male", "man", "boy", "guy", "he", "him"}
	female_terms := []string{"female", "woman", "girl", "lady", "she", "her"}
	nb_terms := []string{"non-binary", "nonbinary", "nb", "enby"}

	for t in nb_terms {
		if strings.contains(lower, t) { return strings.clone("non-binary") }
	}
	for t in female_terms {
		if strings.contains(lower, t) { return strings.clone("female") }
	}
	for t in male_terms {
		if strings.contains(lower, t) { return strings.clone("male") }
	}
	return ""
}

extract_hair_color :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	colors := []string{"black", "brown", "blonde", "blond", "red", "auburn", "brunette", "silver", "gray", "grey", "white", "blue", "green", "purple", "pink", "orange", "golden", "platinum", "chestnut", "strawberry"}
	for c in colors {
		if strings.contains(lower, c) {
			return strings.clone(c)
		}
	}
	return ""
}

extract_hair_style :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	styles := []string{"long", "short", "medium", "curly", "straight", "wavy", "spiky", "spikey", "ponytail", "bun", "braid", "buzz cut", "bald", "mohawk", "pixie", "bob", "afro", "dreadlocks", "dreads", "crew cut", "layered"}
	for s in styles {
		if strings.contains(lower, s) {
			return strings.clone(s)
		}
	}
	return ""
}

extract_eye_color :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	colors := []string{"blue", "brown", "green", "hazel", "amber", "gray", "grey", "violet", "purple", "black", "red"}
	for c in colors {
		if strings.contains(lower, c) {
			return strings.clone(c)
		}
	}
	return ""
}

extract_skin_tone :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	tones := []string{"fair", "pale", "light", "medium", "tan", "olive", "brown", "dark", "ebony", "porcelain", "bronze", "caramel", "warm", "cool"}
	for t in tones {
		if strings.contains(lower, t) {
			return strings.clone(t)
		}
	}
	return ""
}

extract_body_type :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	types := []string{"slim", "skinny", "thin", "average", "athletic", "muscular", "heavy", "large", "tall", "short", "petite", "stocky", "lean", "broad", "curvy", "slender", "chubby", "fit"}
	for t in types {
		if strings.contains(lower, t) {
			return strings.clone(t)
		}
	}
	return ""
}

extract_outfit :: proc(description: string) -> string {
	lower := strings.to_lower(description)

	// Try "wearing X" pattern
	if idx := strings.index(lower, "wearing "); idx >= 0 {
		rest := lower[idx+len("wearing "):]
		end := len(rest)
		if comma := strings.index(rest, ","); comma >= 0 { end = comma }
		if period := strings.index(rest, "."); period >= 0 && period < end { end = period }
		return strings.clone(rest[:end])
	}

	// Try "dressed in X" pattern
	if idx := strings.index(lower, "dressed in "); idx >= 0 {
		rest := lower[idx+len("dressed in "):]
		end := len(rest)
		if comma := strings.index(rest, ","); comma >= 0 { end = comma }
		return strings.clone(rest[:end])
	}

	return ""
}

extract_accessories :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	accessories := []string{"glasses", "sunglasses", "hat", "cap", "beanie", "scarf", "necklace", "pendant", "earrings", "bracelet", "watch", "ring", "backpack", "bag", "gloves", "belt", "tie", "bow", "crown", "headband"}
	found: [dynamic]string
	for a in accessories {
		if strings.contains(lower, a) {
			append(&found, a)
		}
	}
	if len(found) == 0 {
		return ""
	}
	result := strings.join(found[:], ", ")
	defer delete(found)
	return result
}

extract_distinguishing_features :: proc(description: string) -> string {
	lower := strings.to_lower(description)
	defer delete(lower)

	features := []string{"scar", "scars", "tattoo", "tattoos", "freckles", "mole", "birthmark", "beard", "mustache", "goatee", "monocle", "prosthetic", "piercing", "piercings", "dimples", "cleft chin"}
	found: [dynamic]string
	for f in features {
		if strings.contains(lower, f) {
			append(&found, f)
		}
	}
	if len(found) == 0 {
		return ""
	}
	result := strings.join(found[:], ", ")
	defer delete(found)
	return result
}

parse_description_to_template :: proc(description: string) -> Character_Prompt_Template {
	return Character_Prompt_Template{
		age = extract_age(description),
		gender = extract_gender(description),
		hair_color = extract_hair_color(description),
		hair_style = extract_hair_style(description),
		eye_color = extract_eye_color(description),
		skin_tone = extract_skin_tone(description),
		body_type = extract_body_type(description),
		outfit = extract_outfit(description),
		accessories = extract_accessories(description),
		distinguishing_features = extract_distinguishing_features(description),
	}
}

extract_color_palette :: proc(description: string) -> Color_Palette {
	return Color_Palette{
		hair = extract_hair_color(description),
		eyes = extract_eye_color(description),
		skin = extract_skin_tone(description),
		outfit = extract_outfit(description),
	}
}

template_to_string :: proc(t: Character_Prompt_Template) -> string {
	parts: [dynamic]string

	if len(t.age) > 0 { append(&parts, fmt.tprintf("%s-year-old", t.age)) }
	if len(t.gender) > 0 { append(&parts, t.gender) }
	if len(t.hair_color) > 0 || len(t.hair_style) > 0 {
		hair := ""
		if len(t.hair_color) > 0 { hair = t.hair_color }
		if len(t.hair_style) > 0 {
			if len(hair) > 0 { hair = fmt.tprintf("%s %s", hair, t.hair_style) }
			else { hair = t.hair_style }
		}
		append(&parts, fmt.tprintf("%s hair", hair))
	}
	if len(t.eye_color) > 0 { append(&parts, fmt.tprintf("%s eyes", t.eye_color)) }
	if len(t.skin_tone) > 0 { append(&parts, fmt.tprintf("%s skin", t.skin_tone)) }
	if len(t.body_type) > 0 { append(&parts, fmt.tprintf("%s build", t.body_type)) }
	if len(t.outfit) > 0 { append(&parts, fmt.tprintf("wearing %s", t.outfit)) }
	if len(t.accessories) > 0 { append(&parts, t.accessories) }
	if len(t.distinguishing_features) > 0 { append(&parts, t.distinguishing_features) }

	result := strings.join(parts[:], ", ")
	defer delete(parts)
	return result
}
