<script>
import { Banner } from '@components/Banner';
import InfoBox from '@shell/components/InfoBox';
import { Checkbox } from '@components/Form/Checkbox';
import CopyCode from '@shell/components/CopyCode';
import { LabeledInput } from '@components/Form/LabeledInput';
import KeyValue from '@shell/components/form/KeyValue';
import Taints from '@shell/components/form/Taints';
import { MANAGEMENT } from '@shell/config/types';

import { sanitizeKey, sanitizeIP, sanitizeValue } from '@shell/utils/string';

export default {
  emits: ['copied-windows'],

  components: {
    Banner, Checkbox, CopyCode, InfoBox, KeyValue, LabeledInput, Taints
  },

  props: {
    cluster: {
      type:     Object,
      required: true,
    },

    clusterToken: {
      type:     Object,
      required: true,
    }
  },

  async fetch() {
    await this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE });
  },

  data() {
    return {
      showAdvanced:    false,
      etcd:            true,
      controlPlane:    true,
      worker:          true,
      insecure:        false,
      insecureWindows: false,
      address:         '',
      internalAddress: '',
      nodeName:        '',
      labels:          {},
      taints:          []
    };
  },

  computed: {
    linuxCommand() {
      const out = this.insecure ? [this.clusterToken.insecureNodeCommand] : [this.clusterToken.nodeCommand];

      this.etcd && out.push('--etcd');
      this.controlPlane && out.push('--controlplane');
      this.worker && out.push('--worker');
      this.address && out.push(`--address ${ sanitizeIP(this.address) }`);
      this.internalAddress && out.push(`--internal-address ${ sanitizeIP(this.internalAddress) }`);
      this.nodeName && out.push(`--node-name ${ sanitizeValue(this.nodeName) }`);

      for ( const key in this.labels ) {
        const k = sanitizeKey(key);
        const v = sanitizeValue(this.labels[k]);

        if ( k && v ) {
          out.push(`--label ${ k }=${ v }`);
        }
      }

      for ( const t of this.taints ) {
        const k = sanitizeKey(t.key);
        const v = sanitizeValue(t.value);
        const e = sanitizeValue(t.effect);

        if ( k && v && e ) {
          out.push(`--taints ${ k }=${ v }:${ e }`);
        }
      }

      return out.join(' ');
    },

    windowsCommand() {
      const out = this.insecureWindows ? [this.clusterToken.insecureWindowsNodeCommand] : [this.clusterToken.windowsNodeCommand];

      this.address && out.push(`-Address "${ sanitizeValue(this.address) }"`);
      this.internalAddress && out.push(`-InternalAddress "${ sanitizeValue(this.internalAddress) }"`);
      this.nodeName && out.push(`-NodeName "${ sanitizeValue(this.nodeName) }"`);

      for ( const key in this.labels ) {
        const k = sanitizeKey(key);
        const v = sanitizeValue(this.labels[k]);

        if ( k && v ) {
          out.push(`-Label "${ k }=${ v }"`);
        }
      }

      for ( const t of this.taints ) {
        const k = sanitizeKey(t.key);
        const v = sanitizeValue(t.value);
        const e = sanitizeValue(t.effect);

        if ( k && v && e ) {
          out.push(`-Taint "${ k }=${ v }:${ e }"`);
        }
      }

      return out.join(' ');
    },

    // Clusters need linux nodes with etcd, controlplane, and worker roles before windows nodes can be registration
    readyForWindows() {
      if (!this.cluster.mgmt || !this.cluster.mgmt.isReady) {
        return false;
      }
      const nodes = this.cluster.nodes || [];

      const allRoles = nodes.reduce((all, node) => {
        const { isWorker, isEtcd, isControlPlane } = node;

        if (isWorker && !all.includes('worker')) {
          all.push('worker');
        }
        if (isEtcd && !all.includes('etcd')) {
          all.push('etcd');
        }
        if (isControlPlane && !all.includes('controlPlane')) {
          all.push('controlPlane');
        }

        return all;
      }, []);

      return allRoles.length === 3;
    }

  },

  methods: {
    toggleAdvanced() {
      this.showAdvanced = !this.showAdvanced;
    },

    copiedWindows() {
      this.$emit('copied-windows');
    }
  },
};

</script>

<template>
  <div>
    <InfoBox
      :step="1"
      class="step-box"
    >
      <h3 v-t="'cluster.custom.nodeRole.label'" />
      <h4 v-t="'cluster.custom.nodeRole.detail'" />
      <Checkbox
        v-model:value="etcd"
        label-key="model.machine.role.etcd"
      />
      <Checkbox
        v-model:value="controlPlane"
        label-key="model.machine.role.controlPlane"
      />
      <Checkbox
        v-model:value="worker"
        label-key="model.machine.role.worker"
      />
      <Banner
        v-if="!etcd || !controlPlane || !worker"
        data-testid="node-role-warning"
        color="warning"
        :label="t('cluster.custom.nodeRole.warning')"
      />
    </InfoBox>

    <InfoBox
      v-if="showAdvanced"
      :step="2"
      class="step-box"
    >
      <h3 v-t="'cluster.custom.advanced.label'" />
      <h4 v-t="'cluster.custom.advanced.detail'" />

      <div class="row mb-10">
        <div class="col span-4">
          <LabeledInput
            v-model:value="nodeName"
            label-key="cluster.custom.advanced.nodeName"
          />
        </div>
        <div class="col span-4">
          <LabeledInput
            v-model:value="address"
            label-key="cluster.custom.advanced.publicIp"
          />
        </div>
        <div class="col span-4">
          <LabeledInput
            v-model:value="internalAddress"
            label-key="cluster.custom.advanced.privateIp"
          />
        </div>
      </div>

      <KeyValue
        v-model:value="labels"
        class="mb-10"
        mode="edit"
        :title="t('cluster.custom.advanced.nodeLabel.title')"
        :add-label="t('cluster.custom.advanced.nodeLabel.label')"
        :read-allowed="false"
      />

      <Taints
        v-model:value="taints"
        class="mb-10"
        mode="edit"
        :value="taints"
      />

      <a
        v-t="'generic.hideAdvanced'"
        @click="toggleAdvanced"
      />
    </InfoBox>

    <div
      v-else
      class="mb-20"
    >
      <a
        v-t="'generic.showAdvanced'"
        @click="toggleAdvanced"
      />
    </div>

    <InfoBox
      :step="showAdvanced ? 3 : 2"
      class="step-box"
    >
      <h3 v-t="'cluster.custom.registrationCommand.label'" />
      <h4 v-t="'cluster.custom.registrationCommand.linuxDetail'" />
      <CopyCode
        id="copiedLinux"
        class="m-10 p-10"
      >
        {{ linuxCommand }}
      </CopyCode>
      <Checkbox
        v-if="clusterToken.insecureNodeCommand"
        v-model:value="insecure"
        label-key="cluster.custom.registrationCommand.insecure"
      />

      <template v-if="cluster.supportsWindows">
        <hr
          class="mt-20 mb-20"
          role="none"
        >
        <h4 v-t="'cluster.custom.registrationCommand.windowsDetail'" />
        <Banner
          v-if="readyForWindows"
          color="info"
          label-key="cluster.custom.registrationCommand.windowsWorkersOnly"
          data-testid="ready-for-windows"
        />
        <Banner
          v-if="cluster.isRke1"
          color="warning"
          :label="t('cluster.custom.registrationCommand.windowsDeprecatedForRKE1')"
        />
        <template v-if="readyForWindows">
          <CopyCode
            id="copiedWindows"
            class="m-10 p-10"
            @copied="copiedWindows"
          >
            {{ windowsCommand }}
          </CopyCode>
          <Checkbox
            v-if="clusterToken.insecureWindowsNodeCommand"
            v-model:value="insecureWindows"
            label-key="cluster.custom.registrationCommand.insecure"
          />
          <Banner
            color="info"
            :label="t('cluster.custom.registrationCommand.windowsWarning')"
          />
        </template>
        <Banner
          v-else
          color="info"
          label-key="cluster.custom.registrationCommand.windowsNotReady"
          data-testid="windows-not-ready"
        />
      </template>
    </InfoBox>
  </div>
</template>
