<script>
	import { onMount } from 'svelte'
	import { slide, fade } from 'svelte/transition'
	import { JsonView } from '@zerodevx/svelte-json-view'
	import QueryInput from '$lib/QueryInput.svelte'
	import { state, connect } from '$lib/state'
	import { queryMode, queryState } from '../lib/constants.js'
	import Modal from '../lib/Modal.svelte';
	import {
		defaultQueryCode,
		getClusterNames,
		getTopics,
		mapFromLocalStorage,
		startQuery,
		stopQuery
	} from './+page.js';
	export let errors, data

	let showQuerySettings = true
	let showQueryModal = false
	let queryRunning = ''

	const fontSizes = [30, 50, 67, 80, 90, 100, 110, 120, 133, 150]
	let jsonDisplay = {
		expandAll: true,
		showMetadata: true,
		fontSize: fontSizes.indexOf(100),
		fontUp: () => setFontSize(Math.min(jsonDisplay.fontSize + 1, fontSizes.length - 1)),
		fontDown: () => setFontSize(Math.max(jsonDisplay.fontSize - 1, 0))
	}
	const setFontSize = size => {
		jsonDisplay.fontSize = size
		localStorage.jsonDisplay = JSON.stringify(jsonDisplay)
	}

	let querySettings = {
		topic: null,
		cluster: null,
		mode: queryMode.REAL_TIME,
		jsFilter: false,
		maxItems: 20,
		mutableObjects: false,
		queryCode: defaultQueryCode
	}

	let topics = []
	let clusterNames = []
	const updateTopics = async () => {
		topics = await getTopics(querySettings.cluster)
		if (!querySettings.topic || !topics.includes(querySettings.topic)) {
			querySettings.topic = topics[0]
		}
	}


	onMount(async () => {
		const loadSave = ({ checked }) => {
			if (localStorage) {
				mapFromLocalStorage({
					checked,
					jsonDisplay,
					querySettings,
					clusterNames,
					topics,
				})
				jsonDisplay = jsonDisplay
				querySettings = querySettings
			}
		}

		// Instantly load saved data as if cluster and topic names are accurate
		// This should usually be the case
		loadSave({ checked: false })

		connect()
		clusterNames = await getClusterNames()
		if (!clusterNames.includes(querySettings.cluster)) {
			querySettings.cluster = clusterNames[0]
		}
		await updateTopics()

		// Reload with confirmed truthful values
		// Will only flicker if topic or cluster names have changed
		loadSave({ checked: true })
	})
</script>

<svelte:head>
	<title>{querySettings.topic ? `${querySettings.topic} - ` : ''}Kafka Dance</title>
	<meta name="description" content="Kafka Dance message search" />
</svelte:head>

<section>
	{#if showQuerySettings}
		<div class="query-settings">
			<!--
			<Header />
			<NavBar />
			-->
			<h1>Topic Search</h1>
			<div class="state-error">
				{#if $state.error}
					<span transition:fade={{duration: 100}}>{$state.error}</span>
					{#if $state.errorDetails}
						<div class="state-error-details">{$state.errorDetails}</div>
					{/if}
				{:else}
					&nbsp;
				{/if}
			</div>

			<div class="settings-option">
				<h3>Cluster</h3>
				<select disabled={clusterNames.length === 0} bind:value={querySettings.cluster} name="cluster" id="cluster" on:change={updateTopics}>
					{#each clusterNames as clusterName}
						<option value={clusterName}>{clusterName}</option>
					{/each}
				</select>
			</div>

			<div class="settings-option">
				<h3>Topic</h3>
				<select disabled={topics.length === 0} bind:value={querySettings.topic} name="topic" id="topic">
					{#each topics as topic}
						<option value={topic}>{topic}</option>
					{/each}
				</select>
			</div>

			<div class="settings-option">
				<label>
					Maximum Results
					<input type=number bind:value={querySettings.maxItems} min=0 max=10000>
				</label>
			</div>
			<br/>

			<div class="settings-option">
				<QueryInput
					bind:jsFilter={querySettings.jsFilter}
					bind:mutableObjects={querySettings.mutableObjects}
					bind:queryCode={querySettings.queryCode} />
				{#if querySettings.jsFilter}
					<button class="query-input-button" on:click={() => showQueryModal = true}>Open Editor Window</button>
				{/if}
				{#if showQueryModal}
					<Modal onClickOut={() => showQueryModal = false}
						   onCancel={null}
						   onConfirm={() => showQueryModal = false}
						   confirm="Close"
						   title={'JS Filter'}>
						<QueryInput big
								bind:jsFilter={querySettings.jsFilter}
								bind:mutableObjects={querySettings.mutableObjects}
								bind:queryCode={querySettings.queryCode} />
					</Modal>
				{/if}
			</div>

			<div class="query-button">
				{#if queryRunning && $state.queryState !== queryState.DONE}
					<div transition:slide|local class="stop-button">
						<button class="danger" on:click={() => queryRunning = stopQuery(querySettings)}>
							{queryRunning === queryMode.REAL_TIME ? 'End Real Time' : 'Cancel One-Shot'} Query
						</button>
					</div>
				{:else}
					<div transition:slide|local class="start-buttons colored">
						<button class="colored" on:click={() => queryRunning = startQuery({...querySettings, mode: queryMode.ONE_SHOT})}>
							Start One-Shot
						</button>
						<div class="separator"></div>
						<button class="colored" on:click={() => queryRunning = startQuery({...querySettings, mode: queryMode.REAL_TIME})}>
							Start Real-Time
						</button>
					</div>
				{/if}
			</div>
		</div>
		<hr>
	{/if}

	<div class="data-view-container">
		<div class="data-view-bar">
			<div class="border-between">
				<button class={showQuerySettings ? "query-settings-hider" : "query-settings-shower"}
					on:click={() => showQuerySettings = !showQuerySettings}></button>
				<button class={jsonDisplay.expandAll ? 'selected' : ''}
						on:click={() => jsonDisplay.expandAll = !jsonDisplay.expandAll}>
				Expand All Objects
				</button>
				<button class={jsonDisplay.showMetadata ? 'selected' : ''}
						on:click={() => jsonDisplay.showMetadata = !jsonDisplay.showMetadata}>
				Show Metadata
				</button>
			</div>
			<div style="display: flex; align-items: center">
				{#if $state.itemCount >= 0}
					<div class="data-view-results">
						{$state.itemCount} Messages
						<!-- TODO: Error indicator? -->
						{#if $state.queryState === queryState.DONE}
							<span style="color: green; font-weight: bold;">✓</span>
						{:else if $state.queryState === queryState.LOADING}
							<span class="lds-dual-ring"></span>
						{/if}
					</div>
				{/if}
				<div class="border-between zoom-buttons">
					<button on:click={jsonDisplay.fontDown} style="border-color: #aaa;">-</button>
					<button on:click={jsonDisplay.fontUp}>+</button>
				</div>
			</div>
		</div>
		{#if $state.queryState !== queryState.IDLE}
			<div class="data-view" style={`font-size: ${fontSizes[jsonDisplay.fontSize]}%`}>
				<JsonView json={jsonDisplay.showMetadata ? $state.items : $state.items.map(item => item.value)}
						  depth={jsonDisplay.expandAll ? Infinity : 1}/>
			</div>
		{:else }
			<div class="data-view no-query-data" style={`font-size: ${fontSizes[jsonDisplay.fontSize]}%`}>
				<JsonView json={{value: {"Hey": "There's no data here yet!", "When you start a query": "your results will appear here!"}}}
						  depth={jsonDisplay.expandAll ? Infinity : -1}/>
			</div>
		{/if}
	</div>
</section>

<style>
	hr {
		width: 60%;
		border-style: solid;
		margin-bottom: 1.5em;
		border-color: rgba(0, 0, 0, 0.2);
	}
	@media (min-width: 720px) {
		hr {
			display: none;
		}
	}
	.data-view {
		border-top: none;
	}
	.data-view-container {
		display: flex;
		flex-direction: column;
		flex-grow: 1;
	}
	.data-view-bar {
		background-color: #d7dbf3;
		border-style: solid;
		border-width: 1px;
		border-color: #95c1d3;
		border-bottom: none;
		padding: 0;
		margin: 0;
		display: flex;
		justify-content: space-between;
		align-items: center;
	}
	.border-between {
		border-width: 1px;
		border-style: none;
		display: flex;
		flex-grow: 1;
	}
	.border-between button:last-child {
		border-right: none;
	}
	.zoom-buttons button {
		width: 2.5em;
	}
	.data-view-bar button {
		border-color: white;
		border-style: none;
		border-right: solid;
		border-width: 1px;
		border-radius: 0;
		margin: 0;
	}
	button.selected {
		background-color: #4732a5;
		color: white;
	}
	button.selected:hover {
		background-color: #53429d;
		color: white;
	}
	.data-view-results {
		color: #333;
		font-size: 80%;
		margin-right: 1em;
	}

	h1 {
		width: 100%;
	}

	.query-input-button {
		border-style: none;
		border-radius: 0;
		background-color: #313131;
		color: #d0dde9;
	}
	.query-input-button:hover {
		background-color: #575757;
	}

	.query-type {
		display: flex;
		flex-direction: row;
		justify-content: space-between;
	}

	.query-type label {
		padding-left: 0.5em;
	}

	.query-button {
		text-align: right;
		border-radius: 0;
		border-style: none;
		/* New button CSS */
		display: flex;
		flex-direction: column;
	}
	.start-buttons, .stop-button {
		display: flex;
		flex-grow: 1;
	}

	.separator {
		width: 1em;
	}
	.query-button button {
		flex-grow: 1;
	}
	.query-button button:hover {
		flex-grow: 2;
	}

	.state-error {
		color: #ff2222;
		font-weight: bold;
	}
	.state-error-details {
		color: #ff2222;
		font-weight: normal;
		font-size: 80%;
	}

	/* JsonView config
	:root {
		--nodePaddingLeft: 1rem;
		--nodeBorderLeft: 1px dotted #9ca3af;
		--nodeColor: #6d81a4;
		--bracketHoverBackground: #d1d5db;
		--leafDefaultColor: #9ca3af;
		--leafStringColor: #14cb8f;
		--leafNumberColor: #d97706;
		--leafBooleanColor: #2563eb;
	}

	.bracket {
		color: #d0dde9;
	}
	 */

	.no-query-data {
		opacity: 65%;
	}
</style>
