<template>
  <v-card>

    <v-toolbar v-if="$route.params.sequence" class="fixed">

      <v-toolbar-title>
        Sequence {{$route.params.sequence}}
      </v-toolbar-title>

      <v-spacer></v-spacer>

      <dougal-graph-settings-sequence :aspects="aspects" @update:aspects="configure">
      </dougal-graph-settings-sequence>

      <v-btn icon
        :disabled="!($route.params.sequence > firstSequence)"
        :to="{name: 'graphsBySequence', params: { sequence: firstSequence }}"
        title="Go to the first sequence"
      >
        <v-icon>mdi-skip-backward</v-icon>
      </v-btn>
      <v-btn icon
        :disabled="!prevSequence"
        :to="{name: 'graphsBySequence', params: { sequence: prevSequence }}"
        title="Go to the previous sequence"
      >
        <v-icon>mdi-skip-previous</v-icon>
      </v-btn>
      <v-menu
        :close-on-content-click="false"
        :disabled="!sequences.length"
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn icon v-bind="attrs" v-on="on" :disabled="!sequences.length" title="Jump to sequence…">
            <v-icon>mdi-debug-step-over</v-icon>
          </v-btn>
        </template>

        <v-list>
          <v-list-item>
            <v-autocomplete
              :value="$route.params.sequence*1"
              :items="sequences"
              item-text="sequence"
              item-value="sequence"
              @change="(sequence) => $router.push({name: 'graphsBySequence', params: {sequence}})"
            >
            </v-autocomplete>
          </v-list-item>
        </v-list>
      </v-menu>
      <v-btn icon
        :disabled="!nextSequence"
        :to="{name: 'graphsBySequence', params: { sequence: nextSequence }}"
        title="Go to the next sequence"
      >
        <v-icon>mdi-skip-next</v-icon>
      </v-btn>
      <v-btn icon
        :disabled="!($route.params.sequence < lastSequence)"
        :to="{name: 'graphsBySequence', params: { sequence: lastSequence }}"
        title="Go to the last sequence"
      >
        <v-icon>mdi-skip-forward</v-icon>
      </v-btn>

    </v-toolbar>

    <v-toolbar v-else-if="$route.params.sequence0">

      <v-toolbar-title>
        Sequences {{$route.params.sequence0}}‒{{$route.params.sequence1}}
      </v-toolbar-title>

    </v-toolbar>

    <v-toolbar v-else-if="$route.params.date">

      <v-toolbar-title>
        Date {{$route.params.date}}
      </v-toolbar-title>

    </v-toolbar>

    <v-toolbar v-else-if="$route.params.date0">

      <v-toolbar-title>
        Dates {{$route.params.date0}}‒{{$route.params.date1}}
      </v-toolbar-title>

    </v-toolbar>


    <v-toolbar flat>
    <!--
      This is a “ghost” toolbar so that elements further down in the page are
      not hidden behind the (now position: fixed) real toolbar.
    -->
    </v-toolbar>

    <v-container v-if="sequences.length">
      <v-row v-for="(item, idx) in visibleItems" :key="idx">
        <v-col>
          <component
            :is="item.component"
            :data="attributesFor(item)"
            :settings="preferencesFor(item.component)"
            @update:settings="configure">
          </component>
        </v-col>
      </v-row>
    </v-container>
    <v-card-text class="text-center" v-else-if="!loading">
    This project has no sequences.
    </v-card-text>
    <v-card-text class="text-center" v-else>
    Loading…
    </v-card-text>
  </v-card>
</template>

<style scoped>

.v-toolbar.fixed {
  position: fixed;
  width: 100%;
  z-index: 2;
}

.empty-cell {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  border: 1px dashed lightgray;
  border-radius: 4px;
  padding: 4px;
}
</style>

<script>

import { mapActions, mapGetters } from 'vuex';
import { preferencesλ } from '@/lib/utils.js';
import DougalGraphGunsPressure from '@/components/graph-guns-pressure.vue';
import DougalGraphGunsTiming from '@/components/graph-guns-timing.vue';
import DougalGraphGunsDepth from '@/components/graph-guns-depth.vue';
import DougalGraphGunsHeatmap from '@/components/graph-guns-heatmap.vue';
import DougalGraphArraysIJScatter from '@/components/graph-arrays-ij-scatter.vue';
import DougalGraphSettingsSequence from '@/components/graph-settings-sequence.vue';

export default {
  name: "Graphs",

  components: {
    DougalGraphSettingsSequence,
    DougalGraphArraysIJScatter,
    DougalGraphGunsPressure,
    DougalGraphGunsTiming,
    DougalGraphGunsDepth,
    DougalGraphGunsHeatmap
  },

  data () {
    const items = [
      {
        component: "DougalGraphGunsPressure",
      },
      {
        component: "DougalGraphGunsTiming",
      },
      {
        component: "DougalGraphGunsDepth",
      },
      {
        component: "DougalGraphGunsHeatmap",
      },
      {
        component: "DougalGraphArraysIJScatter",
        attributes: {
        }
      }
    ];

    return {
      items,
      data: null,
      sequences: [],
      jumpToSequence: null,
      aspects: items.map(i => i.component)
    };
  },

  watch: {
    preferences () {
      this.configure(preferencesλ(this.preferences)(this.$options.name, {aspects: this.aspects}))
    }
  },

  computed: {

    getRows() {
      return Array(this.rows).fill().map( (el, idx) => idx );
    },

    getCols () {
      return Array(this.cols).fill().map( (el, idx) => idx );
    },

    visibleItems () {
      return this.items.filter( i => this.aspects.includes(i.component) );
    },

    firstSequence () {
      return this.sequences[this.sequences.length-1]?.sequence;
    },

    prevSequence () {
      const seq = Number(this.$route.params.sequence);
      const val = this.sequences
        .filter(i => i.sequence < seq)
        .map(i => i.sequence)
        .reduce( (acc, cur) => Math.max(acc, cur), -Infinity);

      return isFinite(val) ? val : undefined;
    },

    nextSequence () {
      const seq = Number(this.$route.params.sequence);
      const val = this.sequences
        .filter(i => i.sequence > seq)
        .map(i => i.sequence)
        .reduce( (acc, cur) => Math.min(acc, cur), +Infinity);

      return isFinite(val) ? val : undefined;
    },

    lastSequence () {
      return this.sequences[0]?.sequence;
    },

    ...mapGetters(['user', 'preferences', 'loading', 'serverEvent'])
  },

  methods: {

    configure (data) {
      if ("aspects" in data) {
        this.aspects = [...data.aspects];
      }
      for (const key in data) {
        this.saveUserPreference([`${this.$options.name}.${key}`, data[key]]);
      }
    },

    attributesFor (item) {
      return this.data
        ? Object.assign({
          items: this.data,
          meta: {...this.$route.params}
        }, item?.attributes)
        : null;
    },

    preferencesFor (key, defaults) {
      return preferencesλ(this.preferences)(`${this.$options.name}.${key}`, defaults);
    },

    gotoSequence(seq) {
      this.$route.params.sequence = seq;
    },

    ...mapActions(["api", "showSnack", "saveUserPreference"])
  },

  beforeRouteLeave (to, from, next) {
    this.data = null;
    console.log("beforeRouteLeave");
    next();
  },

  async beforeRouteUpdate (to, from, next) {
    console.log("beforeRouteUpdate");
    this.data = null;
    next();

    const url = `/project/${this.$route.params.project}/sequence/${this.$route.params.sequence}?project=sequence,point,tstamp,geometrypreplot,errorraw,errorfinal,meta&path=$.raw.smsrc`;
    this.data = Object.freeze(await this.api([url]));
    this.sequences = await this.api([`/project/${this.$route.params.project}/sequence`]);
  },

  async beforeRouteEnter (to, from, next) {
    console.log("beforeRouteEnter enter");

    next( async vm => {
      if (vm.$route.params.sequence) {
        const url = `/project/${vm.$route.params.project}/sequence/${vm.$route.params.sequence}?project=sequence,point,tstamp,geometrypreplot,errorraw,errorfinal,meta&path=$.raw.smsrc`;

        vm.data = null;
        vm.api([url]).then( d => vm.data = Object.freeze(d) );
        vm.api([`/project/${vm.$route.params.project}/sequence`]).then( d => vm.sequences = d );
      } else {
        // FIXME Ultra-dirty hack to get a result when navigating directly to ‘Graphs’
        if (!vm.sequences.length) {
          vm.sequences = await vm.api([`/project/${vm.$route.params.project}/sequence`]);
        }
        if (vm.sequences.length) { // Check that the project has at least one sequence
          vm.$router.push({name: "graphsBySequence", params: {
            project: vm.$route.params.project,
            sequence: vm.sequences[0]?.sequence
          }});
        }
      }

      console.log("beforeRouteEnter exit");
    });
  },

  async mounted () {
    console.log("Graphs mounted");
    this.sequences = await this.api([`/project/${this.$route.params.project}/sequence`]);

    if (this.sequences && this.sequences.length) {
      if (!this.$route.params.sequence) {
        this.$router.push({name: "graphsBySequence", params: {
          project: this.$route.params.project,
          sequence: this.sequences[0]?.sequence
        }});
      }

      const url = `/project/${this.$route.params.project}/sequence/${this.$route.params.sequence}?project=sequence,point,tstamp,geometrypreplot,errorraw,errorfinal,meta&path=$.raw.smsrc`;

      this.data = Object.freeze(await this.api([url]));
    }
    console.log("Mount finished");
  }

}

</script>
