<script>
  import template from "lodash/template";
  import { fade } from "svelte/transition";
  import Icon from "$/client/components/Icon.svelte";
  import { log } from "$/client/logging.js";
  import Layout from "../Layout.svelte";
  import api from '$/client/api.js';
  import { onMount } from "svelte";

  export let selected_template;

  let showing_rendered = false;
  let results = "";
  let source = "";
  let variable_json = "{ }";
  let generators = [];

  let variables = {};
  let renderer = () => source;
  let notice = "";
  let last_good = "";

  const list_generators = async () => {
    let [status, data] = await api.get('/api/devtools/djenterator');

    if(status == 200) {
      generators = data;
      selected_template = generators[0];
    } else {
      log.debug("failed to load generators", status);
    }
  }

  const render_template = () => {
    try {
      // avoid rendering when the current template doesn't match the renderer
      if(selected_template == renderer._template) {
        variables = variable_json ? JSON.parse(variable_json): {};
        results = renderer(variables);
        notice = "";
        last_good = results;
      }

      return true;
    } catch(err) {
      notice = err.message;
      results = last_good;
      return false;
    }
  }

  const load_variables = async (template_name) => {
    let res = await fetch(`/djenterator/${template_name}.vars`);

    if(res.status == 200) {
      variable_json = await res.text();
    } else {
      variable_json = '{}';
      notice = `No ${template_name}.vars file found. ${res.status}`;
    }
  }

  const load_template = async (template_name) => {
    let res = await fetch(`/djenterator/${template_name}`);

    if(res.status == 200) {
      source = await res.text();
      last_good = source;
      try {
        renderer = template(source);
        // tag this template renderer so that we don't try to render it against the wrong one
        renderer._template = template_name;
        render_template();
      } catch(error) {
        log.error(error);
        notice = `${error.message}`;
        results = source;
      }
    } else {
      notice = `Error loading ${template_name}: ${res.status}`;
    }
  }

  const toggle_template = () => {
    if(showing_rendered) {
      render_template();
    } else {
      results = renderer.toString();
    }

    showing_rendered = !showing_rendered;
  }

  const copy_code = () => {
    navigator.clipboard.writeText(results).then(() => {
      notice = "Code copied to clipboard.";
    }, () => {
      notice = "Failed copying to clipboard.";
    });
  }

  const canary = '3a025dba-1a62-4169-ae9f-f7cd4104c4f4';
  log.debug("Canary is compiled into build as", canary);

  $: if(variable_json) render_template();

  // this reload the templates when you click on a new one
  const re_render = async (what) => {
    await load_variables(what);
    await load_template(what);
  }

  $: if(selected_template) re_render(selected_template);

  onMount(async () => await list_generators());
</script>

<style>
  content {
    display: flex;
    flex-direction: row;
    width: 100%;
  }

  template-editor {
    display: flex;
    flex-direction: column;
    width: 100%;
    align-items: center;
  }

  pre {
    position: relative;
    height: 90vh;
    max-height: 90vh;
    overflow-y: auto;
  }

  right pre {
    display: flex;
    font-size: 1em;
    flex-basis: 100%;
    margin: 0;
    padding: 0;
  }

  right pre code {
    padding-top: 2rem;
    display: flex;
    flex-basis: 100%;
    border-radius: 0px 4px 4px 0px;
    line-height: unset;
    margin: 0;
  }

  left {
    display: flex;
    flex-grow: 1;
    flex-basis: 70ch;
  }

  left textarea {
    border-radius: 4px 0px 0px 4px;
    margin: 0;
    background-color: var(--color-secondary);
    color: var(--color-bg);
    height: 90vh;
    max-height: 90vh;
  }

  right {
    position: relative;
    display: flex;
    flex-direction: column;
    flex-grow: 3;
    flex-basis: 100ch;
    align-items: stretch;
  }

  status {
    position: absolute;
    z-index: 100;
    top: 0;
    padding-right: 1rem;
    padding-left: 1rem;
    padding-top: 0.1rem;
    width: 90%;
    color: var(--color-bg);
    display: flex;
    box-sizing: border-box;
    background-color: var(--color-secondary);
    border-radius: 0px 4px 0px 0px;
    justify-content: space-evenly;
  }

  status file {
    flex-basis: 90%;
    text-align: right;
  }

  status buttons {
    display: flex;
    justify-content: space-around;
    flex-basis: 10%;
    padding-top: 0.5rem;
  }

  pre notice {
    position: absolute;
    bottom: 0;
    left: 0.3rem;
    right: 0.3rem;
    text-align: right;
    padding: 0.5rem;
    font-size: 1rem;
    background-color: var(--color-bg-tertiary);
    border-radius: 4px 4px 0px 0px;
  }
</style>

<Layout fullscreen={ true } header={ false } testid="page-bando-djenterator">
  <template-editor>
    <select bind:value={ selected_template }>
      {#each generators as template}
        <option value={ template }>{ template }</option>
      {/each}
    </select>

    <content>
      <left>
        <textarea class="editor" bind:value={ variable_json } rows="15"></textarea>
      </left>

      <right>
        <status>
        <buttons>
        <span on:click={ copy_code }><Icon name="copy" size="24" color="var(--color-bg)" /></span>
          <span on:click={ toggle_template }><Icon name="code" size="24" color="var(--color-bg)" /></span>
        </buttons>

        <file>static/djenterator/{ selected_template }</file>
        </status>
        <pre>
          <code>
          {results}
          </code>

          {#if notice}
            <notice in:fade on:click={ () => notice = "" }>
              <b>{ notice }</b>
            </notice>
          {/if}
        </pre>
      </right>
    </content>
    <template-editor>
</Layout>
