/**
 * Sparks, or succession factors.
 */
export interface Spark {
	/**
	 * Spark ID.
	 */
	spark_id: number;
	/**
	 * Regional spark name.
	 */
	name: string;
	/**
	 * Regional spark description.
	 */
	description: string;
	/**
	 * Spark group.
	 * Different star levels of a given spark are different spark IDs but
	 * share a spark group.
	 */
	spark_group: number;
	/**
	 * Spark rarity, or star level.
	 */
	rarity: 1 | 2 | 3;
	/**
	 * Spark type.
	 * Roughly the spark color, with extra subdivisions for white sparks.
	 */
	type: Type;
	/**
	 * Possible effects applied by the spark during inspiration.
	 * A random element is selected from this list according to unknown
	 * distributions, then all effects in that selection are applied.
	 */
	effects: Effect[][];
}

/**
 * Spark types.
 * Roughly the spark color, with extra subdivisions for white sparks.
 */
export enum Type {
	Stat = 1,
	Aptitude = 2,
	Unique = 3,
	Skill = 4,
	Race = 5,
	Scenario = 6,
	CarnivalBonus = 7,
	Distance = 8,
	Hidden = 9,
	Surface = 10,
	Style = 11,
}

/** Mapping of spark types to their names. */
export const TYPE_NAMES: Readonly<Record<Type, string>> = {
	[Type.Stat]: 'Stat (Blue)',
	[Type.Aptitude]: 'Aptitude (Pink)',
	[Type.Unique]: 'Unique (Green)',
	[Type.Skill]: 'Skill',
	[Type.Race]: 'Race',
	[Type.Scenario]: 'Scenario',
	[Type.CarnivalBonus]: 'Carnival Bonus (Scarlet)',
	[Type.Distance]: 'Distance (White)',
	[Type.Hidden]: 'Hidden (White)',
	[Type.Surface]: 'Surface (White)',
	[Type.Style]: 'Style (White)',
};

/**
 * Spark effect types.
 */
export enum Target {
	Speed = 1,
	Stamina = 2,
	Power = 3,
	Guts = 4,
	Wit = 5,
	SkillPoints = 6,
	RandomStat = 7,
	Turf = 11,
	Dirt = 12,
	FrontRunner = 21,
	PaceChaser = 22,
	LateSurger = 23,
	EndCloser = 24,
	Sprint = 31,
	Mile = 32,
	Medium = 33,
	Long = 34,
	Skill = 41,
	CarnivalBonus = 51,
	SpeedCap = 61,
	StaminaCap = 62,
	PowerCap = 63,
	GutsCap = 64,
	WitCap = 65,
}

/**
 * Mapping of spark target types to their names.
 * Note that Skill does not include the skill name.
 */
export const TARGET_NAMES: Readonly<Record<Target, string>> = {
	[Target.Speed]: 'Speed',
	[Target.Stamina]: 'Stamina',
	[Target.Power]: 'Power',
	[Target.Guts]: 'Guts',
	[Target.Wit]: 'Wit',
	[Target.SkillPoints]: 'SP',
	[Target.RandomStat]: 'Random Stat',
	[Target.Turf]: 'Turf aptitude',
	[Target.Dirt]: 'Dirt aptitude',
	[Target.FrontRunner]: 'Front Runner aptitude',
	[Target.PaceChaser]: 'Pace Chaser aptitude',
	[Target.LateSurger]: 'Late Surger aptitude',
	[Target.EndCloser]: 'End Closer aptitude',
	[Target.Sprint]: 'Sprint aptitude',
	[Target.Mile]: 'Mile aptitude',
	[Target.Medium]: 'Medium aptitude',
	[Target.Long]: 'Long aptitude',
	[Target.Skill]: 'hint level',
	[Target.CarnivalBonus]: 'Carnival Bonus level',
	[Target.SpeedCap]: 'Speed cap',
	[Target.StaminaCap]: 'Stamina cap',
	[Target.PowerCap]: 'Power cap',
	[Target.GutsCap]: 'Guts cap',
	[Target.WitCap]: 'Wit cap',
};

/**
 * Effects that a spark can apply.
 */
export interface Effect {
	target: Target;
	value1: number;
	value2?: number;
}

export async function sparks(): Promise<Spark[]> {
	const resp = await fetch('/api/global/spark');
	return resp.json();
}

export interface SparkGroup {
	spark_group: number;
	name: string;
	description: string;
	type: Type;
	effects: Effect[][];
	spark_ids: number[];
}

export function byGroup(sparks: Spark[]): SparkGroup[] {
	const r = new Map<number, SparkGroup>();
	for (const { spark_id, name, description, spark_group, type, effects } of sparks) {
		let g = r.get(spark_group);
		if (g == null) {
			g = { spark_group, name, description, type, effects, spark_ids: [] };
			r.set(spark_group, g);
		}
		g.spark_ids.push(spark_id);
	}
	return [...r.values()];
}
