<script lang="ts">
	import * as z from 'zod';
	import * as ism from '$lib/ism';
	import * as character from '$lib/data/character';
	import * as skill from '$lib/data/skill';
	import * as support from '$lib/data/support';
	import * as scenario from '$lib/data/scenario';
	import * as spark from '$lib/data/spark';
	import * as uma from '$lib/data/uma';
	import { onMount } from 'svelte';
	import { SvelteMap, SvelteSet } from 'svelte/reactivity';
	import CareerOverview from './CareerOverview.svelte';
	import SupportIcon from '$lib/SupportIcon.svelte';
	import SkillIcon from '$lib/SkillIcon.svelte';
	import Spark from '$lib/Spark.svelte';
	import SupportCardGainChart from './SupportCardGainChart.svelte';
	import { DEPENDENT, INDEPENDENT, type SupportCardDatum } from './SupportCardGainChart';

	let characters = new SvelteMap<number, character.Character>();
	let skills = new SvelteMap<number, skill.Skill>();
	let skillGroups = new SvelteMap<number, skill.SkillGroup>();
	let supports = new SvelteMap<number, support.SupportCard>();
	let scenarios = new SvelteMap<number, scenario.Scenario>();
	let sparks = new SvelteMap<number, spark.Spark>();
	let umas = new SvelteMap<number, uma.Uma>();
	onMount(async () => {
		const [c, sk, sg, sc, ss, sp, u] = await Promise.all([
			character.character(),
			skill.skills(),
			skill.skillGroups(),
			support.supports(),
			scenario.scenarios(),
			spark.sparks(),
			uma.uma(),
		]);
		for (const chara of c) {
			characters.set(chara.chara_id, chara);
		}
		for (const skill of sk) {
			skills.set(skill.skill_id, skill);
		}
		for (const group of sg) {
			skillGroups.set(group.skill_group, group);
		}
		for (const card of sc) {
			supports.set(card.id, card);
		}
		for (const scen of ss) {
			scenarios.set(scen.scenario_id, scen);
		}
		for (const spark of sp) {
			sparks.set(spark.spark_id, spark);
		}
		for (const uma of u) {
			umas.set(uma.chara_card_id, uma);
		}
	});

	let files: FileList | undefined = $state();
	let careersOpen = $state(false);
	const parses = $derived.by(async () => {
		if (files == null) {
			return [];
		}
		const r = [];
		for (const f of files) {
			try {
				const b = await f.text();
				const v = JSON.parse(b);
				r.push({ f, ok: ism.Career.parse(v) });
			} catch (err) {
				console.warn({ f, err });
				r.push({ f, err });
			}
		}
		return r;
	});
	let exclude = new SvelteSet<string>();
	const errors = $derived((await parses).filter((f) => 'err' in f) as Array<{ f: File; err: unknown }>);
	const loaded = $derived((await parses).filter((f) => 'ok' in f) as Array<{ f: File; ok: ism.Career }>);
	const careers = $derived(loaded.filter((f) => !exclude.has(f.f.name)).map((f) => f.ok));

	let supportGainX: keyof SupportCardDatum = $state('Friendship Bonus');
	let supportGainY: keyof SupportCardDatum = $state('Total Stats');
	let supportGainS: keyof SupportCardDatum = $state('Source');

	function groupskill(g: skill.SkillGroup | undefined, rarity: ism.SkillTip['rarity']) {
		if (g == null) {
			return undefined;
		}
		const s = [g.skill1, g.skill2, g.skill3, g.skill_bad].map((id) => skills.get(id ?? 0)).filter((x) => x != null);
		return s.find((skill) => skill.rarity === rarity);
	}

	function setExclude(name: string, checked: boolean) {
		if (checked) {
			exclude.delete(name);
		} else {
			exclude.add(name);
		}
	}
</script>

<h1 class="text-4xl">Idle Single Mode Analysis</h1>
<form class="mx-auto mt-8 rounded-md p-4 text-center shadow-md ring md:max-w-2xl">
	<input type="file" multiple bind:files accept="application/json" class="h-8 w-full hover:cursor-pointer" />
</form>

{#each errors as err (err.f.name)}
	<div
		class="mx-auto my-2 w-3xl border-2 border-amber-300 bg-amber-200 p-4 text-amber-800 dark:border-amber-800 dark:bg-amber-900 dark:text-amber-200"
	>
		<span class="text-lg">{err.f.name}</span>
		<ul class="list-disc pl-4">
			{#if err.err instanceof z.ZodError}
				{#each err.err.issues as issue (issue.path)}
					<li>{issue.path}: {issue.message}</li>
				{/each}
			{/if}
		</ul>
	</div>
{/each}

{#if loaded.length > 0}
	<div class="mx-auto my-8 max-w-6xl rounded-md border p-4">
		<details class="w-full" bind:open={careersOpen}>
			<summary>
				{(files?.length ?? 0) - errors.length} careers
				{#if exclude.size !== 0}
					({loaded.length - careers.length} excluded)
				{/if}
			</summary>
			{#if careersOpen}
				{#each loaded as career (career.ok.end_info.chara_info.single_mode_chara_id)}
					{@const uma = umas.get(career.ok.end_info.chara_info.card_id)}
					{@const scen = scenarios.get(career.ok.end_info.chara_info.scenario_id)}
					<CareerOverview career={career.ok} bind:enable={() => !exclude.has(career.f.name), (v) => setExclude(career.f.name, v)}>
						{#snippet chara()}
							{uma?.name}
						{/snippet}
						{#snippet scenario()}
							{scen?.name}
						{/snippet}
						{#snippet support(card: ism.SupportCard)}
							{@const s = supports.get(card.support_card_id)}
							<div class="flex flex-col text-center">
								<SupportIcon icon_id={card.support_card_id} size={64} alt={s?.name} />
								<span class="block text-sm">{'◆'.repeat(card.limit_break_count)}{'◇'.repeat(4 - card.limit_break_count)}</span>
							</div>
						{/snippet}
						{#snippet skillHint(hint: ism.SkillTip)}
							{@const g = skillGroups.get(hint.group_id)}
							{@const s = groupskill(g, hint.rarity)}
							<div class="block rounded-md border p-2">
								{#if s != null}
									<SkillIcon class="m-2" icon_id={s.icon_id} size={32} />
									<span>{s.name}</span>
									<span class="ml-auto">+{hint.level}</span>
								{/if}
							</div>
						{/snippet}
						{#snippet spark(id: number)}
							{@const spark = sparks.get(id)}
							{#if spark != null}
								<Spark {spark} />
							{/if}
						{/snippet}
					</CareerOverview>
				{/each}
			{/if}
		</details>
	</div>

	<div class="flex">
		<select class="flex-1" bind:value={supportGainY}>
			{#each DEPENDENT as t (t.name)}
				<option value={t.name}>{t.name}</option>
			{/each}
		</select>
		<span class="mx-2 flex-none">vs</span>
		<select class="flex-1" bind:value={supportGainX}>
			{#each INDEPENDENT as t (t.name)}
				<option value={t.name}>{t.name}</option>
			{/each}
		</select>
	</div>
	<div class="mx-auto mb-8 h-96 w-4xl">
		<SupportCardGainChart {careers} {supports} {scenarios} x={supportGainX} y={supportGainY} symbol={supportGainS} />
	</div>
{/if}
