<script>
import Labels from '@/components/form/Labels';
import Networking from '@/edit/rio.cattle.io.service//Networking';
import Command from '@/edit/rio.cattle.io.service/Command';
import HealthCheck from '@/components/form/HealthCheck';
import { get } from '@/utils/object';
import { CONFIG_MAP, SECRET, RIO } from '@/config/types';
import Loading from '@/components/Loading';
import Tab from '@/components/Tabbed/Tab';
import Tabbed from '@/components/Tabbed';
import CreateEditView from '@/mixins/create-edit-view';
import { _EDIT, EDIT_CONTAINER, DEMO } from '@/config/query-params';
import Footer from '@/components/form/Footer';
import { findBy, filterBy, removeObject } from '@/utils/array';
import { allHash } from '@/utils/promise';
import DEMOS from '@/config/demos';
import Volumes from './Volumes';
import Upgrading from './Upgrading';
import Security from './Security';
import Top from './Top';

export default {
  name: 'CruService',

  components: {
    Loading,
    Tabbed,
    Tab,
    Top,
    Command,
    HealthCheck,
    Networking,
    Labels,
    Security,
    Upgrading,
    Volumes,
    Footer
  },

  mixins: [CreateEditView],

  props: {
    realMode: {
      type:     String,
      required: true,
    },
  },

  async fetch() {
    const hash = await allHash({
      configMaps: this.$store.dispatch('cluster/findAll', { type: CONFIG_MAP }),
      secrets:    this.$store.dispatch('cluster/findAll', { type: SECRET }),
      services:   this.$store.dispatch('cluster/findAll', { type: RIO.SERVICE }),
    });

    this.allSecrets = hash.secrets;
    this.allConfigMaps = hash.configMaps;
  },

  data() {
    if ( !this.value.spec ) {
      this.value.spec = {};
    }

    const containerName = this.$route.query[EDIT_CONTAINER];
    const rootSpec = this.value.spec;
    const multipleContainers = ( !!(rootSpec.containers && rootSpec.containers.length) );
    let spec = rootSpec;
    let isSidecar = false;
    let nameResource = this.value.metadata;

    if ( !nameResource ) {
      nameResource = { name: '' };
      this.value.metadata = nameResource;
    }

    if ( containerName ) {
      nameResource = spec.containers[name];
      spec = nameResource.spec;
      isSidecar = true;
    }

    if ( typeof spec.imagePullPolicy === 'undefined' ) {
      spec.imagePullPolicy = 'Always';
    }

    const demoName = this.$route.query[DEMO];
    let isDemo = false;

    if ( demoName && DEMOS[demoName] ) {
      isDemo = true;
      Object.assign(spec, DEMOS[demoName].spec);
    }

    return {
      multipleContainers,
      nameResource,
      containerName,
      isSidecar,
      rootSpec,
      spec,
      isDemo,
      allConfigMaps: null,
      allSecrets:    null,
      showTabs:      false
    };
  },

  computed: {
    promptForContainer() {
      return this.mode === _EDIT && this.multipleContainers && this.containerName === undefined;
    },

    namespace() {
      return this.value.metadata.namespace;
    },

    configMaps() {
      return matchingNamespaceGroupedByKey(this.allConfigMaps, this.namespace);
    },

    secrets() {
      return matchingNamespaceGroupedByKey(this.allSecrets, this.namespace);
    },
  },

  methods: {
    selectContainer(name) {
      this.$router.applyQuery({ [EDIT_CONTAINER]: name });
      this.containerName = name;
    },

    remove(name) {
      const containers = this.value.spec.containers;
      const entry = findBy(containers, 'name', name);

      removeObject(containers, entry);
      this.save();
    },

    toggleTabs() {
      this.showTabs = !this.showTabs;
    },

    get
  },
};

function matchingNamespaceGroupedByKey(ary, namespace) {
  if ( !namespace ) {
    return [];
  }

  const matching = filterBy((ary || []), 'metadata.namespace', namespace);
  const out = [];

  for ( const item of matching ) {
    const name = item.metadata.name;
    const keys = [];

    for ( const k of Object.keys(item.data || {}) ) {
      keys.push({ label: k, value: `${ name }/${ k }` });
    }

    for ( const k of Object.keys(item.binaryData || {}) ) {
      keys.push({ label: k, value: `${ name }/${ k }` });
    }

    if ( keys.length ) {
      out.push({
        group: item.metadata.name,
        items: keys
      });
    }
  }

  return out;
}

</script>

<template>
  <form>
    <Loading v-if="$fetchState.pending" />
    <div v-else-if="promptForContainer" class="clearfix">
      <p>This service consists of multiple containers, which one do you want to edit?</p>
      <div class="box">
        <p>The primary container</p>
        <p>{{ value.nameDisplay }}</p>
        <button type="button" class="btn role-primary" @click="selectContainer('')">
          Edit
        </button>
      </div>
      <div v-for="choice in value.spec.containers" :key="choice.name" class="box">
        <p>Sidecar</p>
        <p>{{ choice.name }}</p>
        <button type="button" class="btn role-primary" @click="selectContainer(choice.name)">
          Edit
        </button>
        <button type="button" class="btn bg-error" @click="remove(choice.name)">
          Delete
        </button>
      </div>
    </div>
    <div v-else>
      <Top
        :value="value"
        :spec="spec"
        :name-resource="nameResource"
        :is-sidecar="isSidecar"
        :mode="mode"
        :real-mode="realMode"
        :is-demo="isDemo"
        :register-after-hook="registerAfterHook"
        :register-before-hook="registerBeforeHook"
      />
      <div class="spacer"></div>
      <a href="#" @click.prevent="toggleTabs">
        <span v-if="!showTabs">Show</span> <span v-else>Hide</span> additional options
      </a>
      <Tabbed v-show="showTabs" default-tab="command">
        <Tab name="command" label="Command">
          <Command
            :spec="spec"
            :mode="mode"
            :config-maps="configMaps"
            :secrets="secrets"
            :namespace="namespace"
            :more-add="true"
          />
        </Tab>
        <Tab name="network" label="Network">
          <Networking :spec="spec" :mode="mode" />
        </Tab>
        <Tab name="healthcheck" label="Health Check">
          <HealthCheck :spec="spec" :mode="mode" />
        </Tab>
        <Tab v-if="!isSidecar" name="labels" label="Labels">
          <Labels :value="value" :mode="mode" />
        </Tab>
        <Tab name="security" label="Security">
          <Security :spec="spec" :mode="mode" />
        </Tab>
        <Tab name="upgrading" label="Scaling & Upgrading">
          <Upgrading :spec="rootSpec" :concurrency="get(rootSpec, 'autoscale.concurrency')" :mode="mode" />
        </Tab>
        <Tab v-if="false" name="volumes" label="Volumes">
          <Volumes :spec="spec" :mode="mode" />
        </Tab>
      </Tabbed>

      <Footer :mode="mode" :errors="errors" @save="save" @done="done" />
    </div>
  </form>
</template>

<style lang="scss" scoped>
  .box {
    float: left;
    border: 1px solid var(--border);
    padding: 20px;
    text-align: center;
    width: 25%;
    margin-right: 20px;

    P {
      margin: 0;
    }

    &:last-child {
      margin-right: 0;
    }
  }
</style>
