<script>
  import { link } from 'svelte-spa-router';
  import { onMount } from 'svelte';
  import Layout from '$/client/Layout.svelte';
  import Icon from '$/client/components/Icon.svelte';
  import Code from "$/client/components/Code.svelte";
  import HTML from "$/client/components/HTML.svelte";
  import api from "$/client/api.js";

  let index = {};
  let docs_data;
  let url = "/docs/";
  export let params;

  const caps_to_icon = {
    "BUG": "bug",
    "TODO": "clipboard-check",
    "WARNING": "alert-triangle",
    "FOOTGUN": "bomb",
    "DEPRECATED": "axe"
  }

  const jump = (id) => {
    let node = document.getElementById(id);
    if(node) node.scrollIntoView();
  }

  const jump_top = () => jump("top-scroll");

  const load_docs = async (to_load) => {
    // only load if the URL changed
    if(to_load !== url) {
      const [status, data] = await api.get(`/docs/api/${to_load}.json`);

      docs_data = status === 200 ? data : {};
      url = to_load;
      jump_top();
    }
  }

  const load_index = async () => {
    const [status, data] = await api.get("/docs/api/index.json");
    index = status === 200 ? data : {};
  }

  const type_to_syntax = {
    "callexpression": "()",
    "objectexpression": "{}",
    "function": "()",
    "class": "{}",
    "method": "()"
  }

  onMount(load_index);

  $: if(params.wild) {
    // load_docs will ignore any calls where params.wild doesn't change url
    load_docs(params.wild)
  } else {
    url = "/docs/";
  }
</script>

<style>
  sidebar {
    max-width: 300px;
    min-height: 100vh;
    height: 100vh;
    max-height: 100vh;
    margin: unset;
  }

  sidebar items {
    overflow-y: auto;
  }

  right {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    height: 100vh;
    max-height: 100vh;
    overflow-y: auto;
    width: 100%;
  }

  right > div {
    padding: 0.5rem;
  }

  export {
    border-top: 1px solid var(--value5);
    padding: 0.5rem;
  }

  export.member {
    padding-left: 1.5rem;
  }

  export.class-def {
    background-color: var(--value7);
  }

  export > heading {
    display: flex;
    flex-direction: column;
    width: 100%;
    margin-bottom: 1rem;
  }

  export > heading h4,
  export > heading h2,
  export > heading h1
  {
    margin-top: 0.5rem;
    font-family: var(--font-family);
    font-weight: 600;
  }

  export > heading meta-data {
    display: grid;
    gap: 0.5rem;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: auto;
  }

  export > info {
    display: block;
    padding-top: 0.5rem;
  }

  export > info commment {
    display: block;
  }

  /* FOOTGUN: https://github.com/sveltejs/svelte/issues/2967
     When you @html in Svelte it can't apply any styles from here.
     You have to scope the a tag style inside module-header, BUT,
     set it to global so Svelte will apply it to the whole doc,
     not its special class.
   */
  module-header :global(a) {
    color: var(--color-text-inverted);
  }

  module-header {
    display: block;
    padding: 0.5rem;
    background-color: var(--color-bg-inverted);
    color: var(--color-text-inverted);
  }

  module-header :global(h2),
  module-header :global(h3),
  module-header :global(h4) {
    margin-top: 3rem;
  }


  toc {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    background-color: var(--value3);
    color: var(--value9);
  }

  toc span {
    border: 1px solid black;
    padding: 0.5rem;
    text-align: center;
  }

  .no-doc {
    background-color: var(--color-error);
  }

  @media only screen and (max-width: 600px) {
    content {
      flex-direction: column;
    }

    content > right,
    content > left {
      max-width: 100%;
      min-width: 100%;
      width: 100%;
      overflow-y: initial;
      padding-left: 0px;
      padding-right: 0px;
    }

    toc {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      padding: 0px;
      font-size: 0.8em;
    }
  }
</style>


<Layout footer={ false} header={ false } centered={ true } fullwidth={ true }>
  <content>
  <sidebar class:mobile-hide={ url !== "/docs/" }>
  <top><h4><a href="/" use:link><Icon name="arrow-left-circle" /> API Docs</a> </h4></top>
    <items>
    <a class:active={ url === "/docs/" } href="/docs/" use:link>Introduction</a>
    {#each Object.keys(index) as item}
      <a class:active={ item === url } href="/docs/{item}" use:link>{item}</a>
    {/each}
  </items>
  </sidebar>

  <right>
    <span id="top-scroll"></span>
    <div class:mobile-hide={ url === "/docs/" } class:mobile={ url !== "/docs/" } >
      <a href="/docs/" use:link><Icon name="arrow-left-circle" /> { url }</a>
    </div>
    {#if url === "/docs/"}
      <div>
        <HTML url="/docs/api/index.html" />
      </div>
    {:else if docs_data}
        <toc>
          {#each docs_data.exports as exp}
            <span class:no-doc={ !exp.comment } on:click={ () => jump(exp.slug) }>{ exp.name }
              {#each exp.caps as cap_word}<Icon name={ caps_to_icon[cap_word] } size="24" light={ true }/>{/each}
            </span>

            {#if exp.isa == "class"}
              {#each exp.methods as member}
                <span class:no-doc={ !member.comment } on:click={ () => jump(member.slug) }>.{ member.name }
                  {#each member.caps as cap_word}<Icon name={ caps_to_icon[cap_word] } size="24" light={ true } />{/each}
                </span>
              {/each}
            {/if}

          {/each}
        </toc>
        <module-header>
          <h1>{ url }</h1>
          {#if docs_data.comment}
            {@html docs_data.comment}
          {/if}
        </module-header>

      {#each docs_data.exports as exp}
        {#if exp.isa === "class"}
          <export class="class-def">
          <heading>
          <h2 on:click={ () => jump_top() } id={ exp.slug }>class { exp.name }</h2>
            <Code content={ exp.code } language="javascript" />
          </heading>
          <comment>
            {#if exp.comment}
              {@html exp.comment}
            {/if}
          </comment>
          </export>

          {#each exp.methods as member}
            <export class="member">
              <heading>
              <h4 id={ member.slug } on:click={ () => jump(exp.slug) }>.{member.name}{ type_to_syntax[member.isa] || "" }
              </h4>
                <meta-data>
                  {docs_data.source}:{ member.line_start }
                  <em>{ member.isa } of { exp.name }</em>
                  {#if member.static}<b>static</b>{/if}
                  {#if member.async}<b>async</b>{/if}
                  {#if member.generator}<b>generator</b>{/if}
                </meta-data>
              </heading>
              <info>
                {#if member.comment}
                  <comment>
                    { @html member.comment }
                  </comment>
                {/if}
                <Code content={ member.code } language="javascript" />
              </info>
            </export>
          {/each}
        {:else}
          <export>
            <heading>
              <h4 on:click={ () => jump_top() }
                  id={ exp.slug }>{exp.name}{ type_to_syntax[exp.isa] || "" }
              </h4>
              <meta-data>
                {docs_data.source}:{ exp.line_start }
                <em>{ exp.isa }</em>
                {#if exp.static}<b>static</b>{/if}
                {#if exp.async}<b>async</b>{/if}
                {#if exp.generator}<b>generator</b>{/if}
              </meta-data>
            </heading>
            <info>
              {#if exp.comment}
                <comment>
                {@html exp.comment}
                </comment>
              {/if}
              <Code content={ exp.code } language="javascript" />
            </info>
          </export>
        {/if}
      {/each}
    {/if}
  </right>
  </content>
</Layout>
