<script>
import debounce from 'lodash/debounce';
import { mapState, mapGetters } from 'vuex';
import { mapPref, DEV, EXPANDED_GROUPS, FAVORITE_TYPES } from '@/store/prefs';
import ActionMenu from '@/components/ActionMenu';
import Jump from '@/components/nav/Jump';
import WindowManager from '@/components/nav/WindowManager';
import PromptRemove from '@/components/PromptRemove';
import Group from '@/components/nav/Group';
import Header from '@/components/nav/Header';
import Footer from '@/components/nav/Footer';
import { COUNT, SCHEMA, MANAGEMENT } from '@/config/types';
import { BASIC, FAVORITE, USED } from '@/store/type-map';
import { addObjects, replaceWith, clear } from '@/utils/array';
import { NAME as EXPLORER } from '@/config/product/explorer';
import isEqual from 'lodash/isEqual';

export default {

  components: {
    Jump,
    PromptRemove,
    Header,
    Footer,
    ActionMenu,
    Group,
    WindowManager
  },

  data() {
    return { groups: [] };
  },

  middleware: ['authenticated'],

  computed: {
    ...mapState(['managementReady', 'clusterReady']),
    ...mapGetters(['productId']),
    ...mapGetters({ locale: 'i18n/selectedLocaleLabel' }),

    namespaces() {
      return this.$store.getters['namespaces']();
    },

    dev:            mapPref(DEV),
    expandedGroups: mapPref(EXPANDED_GROUPS),
    favoriteTypes:  mapPref(FAVORITE_TYPES),

    allSchemas() {
      const inStore = this.$store.getters['currentProduct'].inStore;

      return this.$store.getters[`${ inStore }/all`](SCHEMA);
    },

    counts() {
      const inStore = this.$store.getters['currentProduct'].inStore;

      // So that there's something to watch for updates
      if ( this.$store.getters[`${ inStore }/haveAll`](COUNT) ) {
        const counts = this.$store.getters[`${ inStore }/all`](COUNT)[0].counts;

        return counts;
      }

      return {};
    },

    showJump() {
      return this.productId === EXPLORER;
    },
  },

  watch: {
    counts() {
      this.queueUpdate();
    },

    allSchemas() {
      this.queueUpdate();
    },

    favoriteTypes() {
      this.queueUpdate();
    },

    locale(a, b) {
      if ( !isEqual(a, b) ) {
        this.getGroups();
      }
    },

    productId(a, b) {
      if ( !isEqual(a, b) ) {
        // Immediately update because you'll see it come in later
        this.getGroups();
      }
    },

    namespaces(a, b) {
      if ( !isEqual(a, b) ) {
        // Immediately update because you'll see it come in later
        this.getGroups();
      }
    },

    clusterReady(a, b) {
      if ( !isEqual(a, b) ) {
        // Immediately update because you'll see it come in later
        this.getGroups();
      }
    },

    product(a, b) {
      if ( !isEqual(a, b) ) {
        // Immediately update because you'll see it come in later
        this.getGroups();
      }
    },
  },

  created() {
    this.queueUpdate = debounce(this.getGroups, 500);

    this.getGroups();
  },

  methods: {
    getGroups() {
      if ( !this.clusterReady ) {
        clear(this.groups);

        return;
      }

      const clusterId = this.$store.getters['clusterId'];
      const productId = this.$store.getters['productId'];
      const currentType = this.$route.params.resource || '';
      let namespaces = null;

      if ( !this.$store.getters['isAllNamespaces'] ) {
        namespaces = Object.keys(this.namespaces);
      }

      const namespaceMode = this.$store.getters['namespaceMode'];
      const out = [];
      const modes = [BASIC];

      if ( productId === EXPLORER ) {
        modes.push(FAVORITE);
        modes.push(USED);
      }
      for ( const mode of modes ) {
        const types = this.$store.getters['type-map/allTypes'](productId, mode) || {};
        const more = this.$store.getters['type-map/getTree'](productId, mode, types, clusterId, namespaceMode, namespaces, currentType);

        addObjects(out, more);
      }

      replaceWith(this.groups, ...out);
    },

    expanded(name) {
      const currentType = this.$route.params.resource || '';

      return this.expandedGroups.includes(name) || name === currentType;
    },

    toggleNoneLocale() {
      this.$store.dispatch('i18n/toggleNone');
    },

    toggleTheme() {
      this.$store.dispatch('prefs/toggleTheme');
    },

    wheresMyDebugger() {
      // vue-shortkey is preventing F8 from passing through to the browser... this works for now.
      // eslint-disable-next-line no-debugger
      debugger;
    },

    async toggleShell() {
      const clusterId = this.$route.params.cluster;

      if ( !clusterId || !this.$store.getters['isMultiCluster'] ) {
        return;
      }

      const cluster = await this.$store.dispatch('management/find', {
        type: MANAGEMENT.CLUSTER,
        id:   clusterId,
      });

      if (!cluster ) {
        return;
      }

      cluster.openShell();
    }
  },

  head() {
    const theme = this.$store.getters['prefs/theme'];

    return {
      bodyAttrs: { class: `theme-${ theme } overflow-hidden dashboard-body` },
      title:     this.$store.getters['i18n/t']('nav.title'),
    };
  },

};
</script>

<template>
  <div v-if="managementReady" class="dashboard-root">
    <Header />

    <nav v-if="clusterReady">
      <Jump v-if="showJump" class="m-10" />
      <div v-else class="mb-20" />
      <template v-for="(g, idx) in groups">
        <Group
          :key="idx"
          id-prefix=""
          class="package"
          :expanded="expanded"
          :group="g"
          :can-collapse="!g.isRoot"
          :show-header="!g.isRoot"
        >
          <template #header>
            <h6>{{ g.label }}</h6>
          </template>
        </Group>
      </template>
    </nav>

    <main v-if="clusterReady">
      <nuxt class="outlet" />
      <Footer />

      <ActionMenu />
      <PromptRemove />
      <button v-if="dev" v-shortkey.once="['shift','l']" class="hide" @shortkey="toggleNoneLocale()" />
      <button v-if="dev" v-shortkey.once="['shift','t']" class="hide" @shortkey="toggleTheme()" />
      <button v-shortkey.once="['f8']" class="hide" @shortkey="wheresMyDebugger()" />
      <button v-shortkey.once="['`']" class="hide" @shortkey="toggleShell" />
    </main>

    <div class="wm">
      <WindowManager />
    </div>
  </div>
</template>

<style lang="scss">
  .dashboard-root {
    display: grid;
    height: 100vh;

    grid-template-areas:
      "header  header"
      "nav      main"
      "wm       wm";

    grid-template-columns: var(--nav-width)     auto;
    grid-template-rows:    var(--header-height) auto var(--wm-height, 0px);

    > HEADER {
      grid-area: header;
    }

    NAV {
      grid-area: nav;
      position: relative;
      background-color: var(--nav-bg);
      overflow-y: auto;

      .package.depth-0 {
        .root .label {
        }

        &.expanded > .body {
          margin-bottom: 5px;
        }
      }

      .header {
        background: transparent;
        padding-left: 10px;
      }

      H6, .root.child .label {
        margin: 0;
        letter-spacing: 0.1em;
        line-height: initial;

        A { padding-left: 0; }
      }
    }
  }

  MAIN {
    grid-area: main;
    overflow: auto;

    .outlet {
      display: flex;
      flex-direction: column;
      padding: 20px 20px 70px 20px;
      min-height: 100%;
      margin-bottom: calc(-1 * var(--footer-height) - 1px);
    }

    FOOTER {
      background-color: var(--nav-bg);
      height: var(--footer-height);
    }

    HEADER {
      display: grid;
      grid-template-areas:  "title actions"
                            "state-banner state-banner";
      grid-template-columns: "auto min-content";
      margin-bottom: 20px;
      align-items: center;

      H1 {
        grid-area: title;
        margin: 0;
      }

      .state-banner {
        grid-area: state-banner;
      }

      .actions {
        grid-area: actions;
        text-align: right;
      }
    }

  }

  .wm {
    grid-area: wm;
    overflow-y: hidden;
  }
</style>
