<!-- 
    @component

    Properties:
    - metrics:    [String] (changes from inside, needs to be initialised, list of selected metrics)
    - isOpen:     Boolean  (can change from inside and outside)
    - configName: String   (constant)
 -->

<script>
  import {
    Modal,
    ModalBody,
    ModalHeader,
    ModalFooter,
    Button,
    ListGroup,
  } from "@sveltestrap/sveltestrap";
  import { getContext } from "svelte";
  import { gql, getContextClient, mutationStore } from "@urql/svelte";

  export let metrics;
  export let isOpen;
  export let configName;
  export let allMetrics = null;
  export let cluster = null;
  export let showFootprint;
  export let view = "job";

  const clusters = getContext("clusters"),
    onInit = getContext("on-init");

  let newMetricsOrder = [];
  let unorderedMetrics = [...metrics];
  let pendingShowFootprint = !!showFootprint;

  onInit(() => {
    if (allMetrics == null) allMetrics = new Set();
    for (let c of clusters)
      for (let metric of c.metricConfig) allMetrics.add(metric.name);
  });

  $: {
    if (allMetrics != null) {
      if (cluster == null) {
        // console.log('Reset to full metric list')
        for (let c of clusters)
          for (let metric of c.metricConfig) allMetrics.add(metric.name);
      } else {
        // console.log('Recalculate available metrics for ' + cluster)
        allMetrics.clear();
        for (let c of clusters)
          if (c.name == cluster)
            for (let metric of c.metricConfig) allMetrics.add(metric.name);
      }

      newMetricsOrder = [...allMetrics].filter((m) => !metrics.includes(m));
      newMetricsOrder.unshift(...metrics.filter((m) => allMetrics.has(m)));
      unorderedMetrics = unorderedMetrics.filter((m) => allMetrics.has(m));
    }
  }

  const client = getContextClient();
  const updateConfigurationMutation = ({ name, value }) => {
    return mutationStore({
      client: client,
      query: gql`
        mutation ($name: String!, $value: String!) {
          updateConfiguration(name: $name, value: $value)
        }
      `,
      variables: { name, value },
    });
  };

  let columnHovering = null;

  function columnsDragStart(event, i) {
    event.dataTransfer.effectAllowed = "move";
    event.dataTransfer.dropEffect = "move";
    event.dataTransfer.setData("text/plain", i);
  }

  function columnsDrag(event, target) {
    event.dataTransfer.dropEffect = "move";
    const start = Number.parseInt(event.dataTransfer.getData("text/plain"));
    if (start < target) {
      newMetricsOrder.splice(target + 1, 0, newMetricsOrder[start]);
      newMetricsOrder.splice(start, 1);
    } else {
      newMetricsOrder.splice(target, 0, newMetricsOrder[start]);
      newMetricsOrder.splice(start + 1, 1);
    }
    columnHovering = null;
  }

  function closeAndApply() {
    metrics = newMetricsOrder.filter((m) => unorderedMetrics.includes(m));
    isOpen = false;

    showFootprint = !!pendingShowFootprint;

    updateConfigurationMutation({
      name: cluster == null ? configName : `${configName}:${cluster}`,
      value: JSON.stringify(metrics),
    }).subscribe((res) => {
      if (res.fetching === false && res.error) {
        throw res.error;
        // console.log('Error on subscription: ' + res.error)
      }
    });

    updateConfigurationMutation({
      name:
        cluster == null
          ? "plot_list_showFootprint"
          : `plot_list_showFootprint:${cluster}`,
      value: JSON.stringify(showFootprint),
    }).subscribe((res) => {
      if (res.fetching === false && res.error) {
        console.log("Error on footprint subscription: " + res.error);
        throw res.error;
      }
    });
  }
</script>

<Modal {isOpen} toggle={() => (isOpen = !isOpen)}>
  <ModalHeader>Configure columns (Metric availability shown)</ModalHeader>
  <ModalBody>
    <ListGroup>
      {#if view === "list"}
        <li class="list-group-item">
          <input type="checkbox" bind:checked={pendingShowFootprint} /> Show Footprint
        </li>
        <hr />
      {/if}
      {#each newMetricsOrder as metric, index (metric)}
        <li
          class="cc-config-column list-group-item"
          draggable={true}
          ondragover="return false"
          on:dragstart={(event) => columnsDragStart(event, index)}
          on:drop|preventDefault={(event) => columnsDrag(event, index)}
          on:dragenter={() => (columnHovering = index)}
          class:is-active={columnHovering === index}
        >
          {#if unorderedMetrics.includes(metric)}
            <input
              type="checkbox"
              bind:group={unorderedMetrics}
              value={metric}
              checked
            />
          {:else}
            <input
              type="checkbox"
              bind:group={unorderedMetrics}
              value={metric}
            />
          {/if}
          {metric}
          <span style="float: right;">
            {cluster == null
              ? clusters // No single cluster specified: List Clusters with Metric
                  .filter(
                    (c) => c.metricConfig.find((m) => m.name == metric) != null,
                  )
                  .map((c) => c.name)
                  .join(", ")
              : clusters // Single cluster requested: List Subclusters with do not have metric remove flag
                  .filter((c) => c.name == cluster)
                  .filter(
                    (c) => c.metricConfig.find((m) => m.name == metric) != null,
                  )
                  .map(function (c) {
                    let scNames = c.subClusters.map((sc) => sc.name);
                    scNames.forEach(function (scName) {
                      let met = c.metricConfig.find((m) => m.name == metric);
                      let msc = met.subClusters.find(
                        (msc) => msc.name == scName,
                      );
                      if (msc != null) {
                        if (msc.remove == true) {
                          scNames = scNames.filter((scn) => scn != msc.name);
                        }
                      }
                    });
                    return scNames;
                  })
                  .join(", ")}
          </span>
        </li>
      {/each}
    </ListGroup>
  </ModalBody>
  <ModalFooter>
    <Button color="primary" on:click={closeAndApply}>Close & Apply</Button>
  </ModalFooter>
</Modal>

<style>
  li.cc-config-column {
    display: block;
    cursor: grab;
  }

  li.cc-config-column.is-active {
    background-color: #3273dc;
    color: #fff;
    cursor: grabbing;
  }
</style>
