<!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
-->

<script lang="ts">
  import Button from '../Button.svelte';
  import Select from '../Select.svelte';
  import { decoderRegistry } from './decoders/utils/decoderRegistry';
  import { decodeBase64 } from '$lib/utils/base64Utils';

  interface Props {
    payload?: string | undefined;
    codec?: string | undefined | null;
  }

  let { payload = undefined, codec = undefined }: Props = $props();

  type ErrorState = { title: string; message: string };
  type DecodedState =
    | { status: 'idle'; forceChangeDecoder: boolean }
    | { status: 'error'; error: ErrorState }
    | { status: 'success'; content: string };

  let decodeState = $state<DecodedState>({ status: 'idle', forceChangeDecoder: false });
  let showRaw = $state(false);
  let selectedDecoder = $state(codec || 'string');

  function getError(type: 'no_payload' | 'unsupported_codec' | 'invalid_format'): ErrorState {
    switch (type) {
      case 'no_payload':
        return {
          title: 'No payload',
          message: 'This message has no payload to decode'
        };
      case 'unsupported_codec':
        return {
          title: 'Unsupported codec',
          message: `The specified codec ${codec} is not supported. Select another decoder from the dropdown below.`
        };
      case 'invalid_format':
        return {
          title: 'Invalid format',
          message: `The payload is not valid ${selectedDecoder.toUpperCase()}`
        };
    }
  }

  function decode() {
    if (!payload) {
      decodeState = { status: 'error', error: getError('no_payload') };
      return;
    }

    const decodedPayload = decodeBase64(payload);
    if (!decodedPayload) {
      decodeState = { status: 'error', error: getError('invalid_format') };
      return;
    }

    const decoder = decoderRegistry.get(selectedDecoder);
    if (!decoder) {
      decodeState = { status: 'error', error: getError('unsupported_codec') };
      return;
    }

    const content = decoder.decode(decodedPayload);
    if (!content) {
      decodeState = { status: 'error', error: getError('invalid_format') };
      return;
    }

    decodeState = { status: 'success', content };
  }
</script>

{#if decodeState.status === 'idle'}
  {#if !codec || !decoderRegistry.get(codec) || decodeState.forceChangeDecoder}
    <div class="mb-4">
      <Select
        label="Select decoder"
        name="decoder"
        options={decoderRegistry.getNames()}
        bind:value={selectedDecoder}
      />
    </div>
  {/if}
  <Button variant="contained" onclick={decode}>Decode</Button>
{:else}
  {#if decodeState.status === 'error'}
    <div class="bg-red-100 dark:bg-red-900 p-4 rounded-md w-full">
      <p class="font-bold">{decodeState.error.title}</p>
      <p>{decodeState.error.message}</p>
    </div>
  {/if}

  {#if decodeState.status === 'success'}
    <div class="flex items-center gap-3">
      <p class="font-bold">Codec: {selectedDecoder}</p>
      <Button
        variant="text"
        onclick={() => (decodeState = { status: 'idle', forceChangeDecoder: true })}
        >Change decoder</Button
      >
    </div>
    <div class="w-full mt-2">
      <pre class="bg-gray-100 dark:bg-gray-800 p-1 rounded-md overflow-auto"><code
          >{decodeState.content}</code
        ></pre>
    </div>
  {/if}

  <div class="mt-4 mb-2">
    <Button variant="text" onclick={() => (showRaw = !showRaw)}>
      {showRaw ? 'Hide' : 'Show'} raw payload (base64)
    </Button>
  </div>

  {#if showRaw && payload}
    <div class="w-full">
      <pre
        class="bg-gray-100 dark:bg-gray-800 p-4 rounded-md overflow-auto whitespace-pre-wrap break-all"><code
          >{payload}</code
        ></pre>
    </div>
  {/if}
{/if}
