<!--
    @component Main cluster node status view component; renders overview or list depending on type

    Properties:
    - `displayType String?`: The type of node display ['OVERVIEW' || 'LIST']
    - `cluster String`: The cluster to show status information for
    - `from Date?`: Custom Time Range selection 'from' [Default: null]
    - `to Date?`: Custom Time Range selection 'to' [Default: null]
 -->

<script>
  import { getContext } from "svelte";
  import {
    Row,
    Col,
    Card,
    Input,
    InputGroup,
    InputGroupText,
    Icon,
    Button,
  } from "@sveltestrap/sveltestrap";

  import { init } from "./generic/utils.js";
  import NodeOverview from "./systems/NodeOverview.svelte";
  import NodeList from "./systems/NodeList.svelte";
  import MetricSelection from "./generic/select/MetricSelection.svelte";
  import TimeSelection from "./generic/select/TimeSelection.svelte";
  import Refresher from "./generic/helper/Refresher.svelte";

  export let displayType;
  export let cluster;
  export let subCluster = "";
  export let from = null;
  export let to = null;

  const { query: initq } = init();

  console.assert(
    displayType == "OVERVIEW" || displayType == "LIST",
    "Invalid nodes displayType provided!",
  );

  if (from == null || to == null) {
    to = new Date(Date.now());
    from = new Date(to.getTime());
    from.setHours(from.getHours() - 12);
  }

  const initialized = getContext("initialized");
  const ccconfig = getContext("cc-config");
  const globalMetrics = getContext("globalMetrics");
  const displayNodeOverview = (displayType === 'OVERVIEW')

  const resampleConfig = getContext("resampling") || null;
  const resampleResolutions = resampleConfig ? [...resampleConfig.resolutions] : [];
  const resampleDefault = resampleConfig ? Math.max(...resampleConfig.resolutions) : 0;
  let selectedResolution = resampleConfig ? resampleDefault : 0;

  let hostnameFilter = "";
  let pendingHostnameFilter = "";
  let selectedMetric = ccconfig.system_view_selectedMetric || "";
  let selectedMetrics = ccconfig[`node_list_selectedMetrics:${cluster}`] || [ccconfig.system_view_selectedMetric];
  let isMetricsSelectionOpen = false;

  /*
    Note 1: "Sorting" as use-case ignored for now, probably default to alphanumerical on hostnames of cluster (handled in frontend at the moment)
    Note 2: Add Idle State Filter (== No allocated Jobs) [Frontend?] : Cannot be handled by CCMS, requires secondary job query and refiltering of visible nodes
  */

  let systemMetrics = [];
  let systemUnits = {};

  function loadMetrics(isInitialized) {
    if (!isInitialized) return
    systemMetrics = [...globalMetrics.filter((gm) => gm?.availability.find((av) => av.cluster == cluster))]
    for (let sm of systemMetrics) {
      systemUnits[sm.name] = (sm?.unit?.prefix ? sm.unit.prefix : "") + (sm?.unit?.base ? sm.unit.base : "")
    }
    if (!selectedMetric) selectedMetric = systemMetrics[0].name
  }

  $: loadMetrics($initialized)

  $: if (displayNodeOverview) {
    selectedMetrics = [selectedMetric]
  }

  $: { // Wait after input for some time to prevent too many requests
    setTimeout(function () {
      hostnameFilter = pendingHostnameFilter;
    }, 500);
  }
</script>

<!-- ROW1: Tools-->
<Row cols={{ xs: 2, lg: !displayNodeOverview ? (resampleConfig ? 5 : 4) : 4 }} class="mb-3">
  {#if $initq.data}
    <!-- List Metric Select Col-->
    {#if !displayNodeOverview}
      <Col>
        <InputGroup>
          <InputGroupText><Icon name="graph-up" /></InputGroupText>
          <InputGroupText class="text-capitalize">Metrics</InputGroupText>
          <Button
            outline
            color="primary"
            on:click={() => (isMetricsSelectionOpen = true)}
          >
            {selectedMetrics.length} selected
          </Button>
        </InputGroup>
      </Col>
      {#if resampleConfig}
        <Col>
          <InputGroup>
            <InputGroupText><Icon name="plus-slash-minus" /></InputGroupText>
            <InputGroupText>Resolution</InputGroupText>
            <Input type="select" bind:value={selectedResolution}>
              {#each resampleResolutions as res}
                <option value={res}
                  >{res} sec</option
                >
              {/each}
            </Input>
          </InputGroup>
        </Col>
      {/if}
    {/if}
    <!-- Node Col-->
    <Col class="mt-2 mt-lg-0">
      <InputGroup>
        <InputGroupText><Icon name="hdd" /></InputGroupText>
        <InputGroupText>Find Node(s)</InputGroupText>
        <Input
          placeholder="Filter hostname ..."
          type="text"
          bind:value={pendingHostnameFilter}
        />
      </InputGroup>
    </Col>
    <!-- Range Col-->
    <Col>
      <TimeSelection bind:from bind:to />
    </Col>
    <!-- Overview Metric Col-->
    {#if displayNodeOverview}
      <Col class="mt-2 mt-lg-0">
        <InputGroup>
          <InputGroupText><Icon name="graph-up" /></InputGroupText>
          <InputGroupText>Metric</InputGroupText>
          <Input type="select" bind:value={selectedMetric}>
            {#each systemMetrics as metric}
              <option value={metric.name}
                >{metric.name} {systemUnits[metric.name] ? "("+systemUnits[metric.name]+")" : ""}</option
              >
            {/each}
          </Input>
        </InputGroup>
      </Col>
    {/if}
    <!-- Refresh Col-->
    <Col class="mt-2 mt-lg-0">
      <Refresher
        on:refresh={() => {
          const diff = Date.now() - to;
          from = new Date(from.getTime() + diff);
          to = new Date(to.getTime() + diff);
        }}
      />
    </Col>
  {/if}
</Row>

<!-- ROW2: Content-->
{#if displayType !== "OVERVIEW" && displayType !== "LIST"}
  <Row>
    <Col>
      <Card body color="danger">Unknown displayList type! </Card>
    </Col>
  </Row>
{:else}
  {#if displayNodeOverview}
    <!-- ROW2-1: Node Overview (Grid Included)-->
    <NodeOverview {cluster} {subCluster} {ccconfig} {selectedMetrics} {from} {to} {hostnameFilter}/>
  {:else}
    <!-- ROW2-2: Node List (Grid Included)-->
    <NodeList {cluster} {subCluster} {ccconfig} {selectedMetrics} {selectedResolution} {hostnameFilter} {from} {to} {systemUnits}/>
  {/if}
{/if}

<MetricSelection
  {cluster}
  configName="node_list_selectedMetrics"
  metrics={selectedMetrics}
  bind:isOpen={isMetricsSelectionOpen}
  on:update-metrics={({ detail }) => {
    selectedMetrics = [...detail]
  }}
/>