<script>
// ee-only
import DashboardMixin from 'ee/monitoring/components/dashboard_mixin';

import _ from 'underscore';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import MonitoringService from '../services/monitoring_service';
import MonitorAreaChart from './charts/area.vue';
import GraphGroup from './graph_group.vue';
import Graph from './graph.vue';
import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub';

export default {
  components: {
    MonitorAreaChart,
    Graph,
    GraphGroup,
    EmptyState,
    Icon,
  },

  // ee-only
  mixins: [DashboardMixin],

  props: {
    hasMetrics: {
      type: Boolean,
      required: false,
      default: true,
    },
    showLegend: {
      type: Boolean,
      required: false,
      default: true,
    },
    showPanels: {
      type: Boolean,
      required: false,
      default: true,
    },
    forceSmallGraph: {
      type: Boolean,
      required: false,
      default: false,
    },
    documentationPath: {
      type: String,
      required: true,
    },
    settingsPath: {
      type: String,
      required: true,
    },
    clustersPath: {
      type: String,
      required: true,
    },
    tagsPath: {
      type: String,
      required: true,
    },
    projectPath: {
      type: String,
      required: true,
    },
    metricsEndpoint: {
      type: String,
      required: true,
    },
    deploymentEndpoint: {
      type: String,
      required: false,
      default: null,
    },
    emptyGettingStartedSvgPath: {
      type: String,
      required: true,
    },
    emptyLoadingSvgPath: {
      type: String,
      required: true,
    },
    emptyNoDataSvgPath: {
      type: String,
      required: true,
    },
    emptyUnableToConnectSvgPath: {
      type: String,
      required: true,
    },
    environmentsEndpoint: {
      type: String,
      required: true,
    },
    currentEnvironmentName: {
      type: String,
      required: true,
    },
    showEnvironmentDropdown: {
      type: Boolean,
      required: false,
      default: true,
    },
  },
  data() {
    return {
      store: new MonitoringStore(),
      state: 'gettingStarted',
      showEmptyState: true,
      hoverData: {},
      elWidth: 0,
    };
  },
  computed: {
    graphComponent() {
      return gon.features && gon.features.areaChart ? MonitorAreaChart : Graph;
    },
    forceRedraw() {
      return this.elWidth;
    },
  },
  created() {
    this.service = new MonitoringService({
      metricsEndpoint: this.metricsEndpoint,
      deploymentEndpoint: this.deploymentEndpoint,
      environmentsEndpoint: this.environmentsEndpoint,
    });
    this.mutationObserverConfig = {
      attributes: true,
      childList: false,
      subtree: false,
    };
    eventHub.$on('hoverChanged', this.hoverChanged);
  },
  beforeDestroy() {
    eventHub.$off('hoverChanged', this.hoverChanged);
    window.removeEventListener('resize', this.resizeThrottled, false);
    this.sidebarMutationObserver.disconnect();
  },
  mounted() {
    this.resizeThrottled = _.debounce(this.resize, 100);
    this.servicePromises = [
      this.service
        .getGraphsData()
        .then(data => this.store.storeMetrics(data))
        .catch(() => Flash(s__('Metrics|There was an error while retrieving metrics'))),
      this.service
        .getDeploymentData()
        .then(data => this.store.storeDeploymentData(data))
        .catch(() => Flash(s__('Metrics|There was an error getting deployment information.'))),
    ];
    if (!this.hasMetrics) {
      this.state = 'gettingStarted';
    } else {
      if (this.showEnvironmentDropdown) {
        this.servicePromises.push(
          this.service
            .getEnvironmentsData()
            .then(data => this.store.storeEnvironmentsData(data))
            .catch(() =>
              Flash(s__('Metrics|There was an error getting environments information.')),
            ),
        );
      }
      this.getGraphsData();
      window.addEventListener('resize', this.resizeThrottled, false);

      const sidebarEl = document.querySelector('.nav-sidebar');
      // The sidebar listener
      this.sidebarMutationObserver = new MutationObserver(this.resizeThrottled);
      this.sidebarMutationObserver.observe(sidebarEl, this.mutationObserverConfig);
    }
  },
  methods: {
    getGraphsData() {
      this.state = 'loading';
      Promise.all(this.servicePromises)
        .then(() => {
          if (this.store.groups.length < 1) {
            this.state = 'noData';
            return;
          }

          this.showEmptyState = false;
        })
        .then(this.resize)
        .catch(() => {
          this.state = 'unableToConnect';
        });
    },
    resize() {
      this.elWidth = this.$el.clientWidth;
    },
    hoverChanged(data) {
      this.hoverData = data;
    },
  },
};
</script>

<template>
  <div v-if="!showEmptyState" :key="forceRedraw" class="prometheus-graphs prepend-top-default">
    <div v-if="showEnvironmentDropdown" class="environments d-flex align-items-center">
      {{ s__('Metrics|Environment') }}
      <div class="dropdown prepend-left-10">
        <button class="dropdown-menu-toggle" data-toggle="dropdown" type="button">
          <span> {{ currentEnvironmentName }} </span> <icon name="chevron-down" />
        </button>
        <div
          v-if="store.environmentsData.length > 0"
          class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up"
        >
          <ul>
            <li v-for="environment in store.environmentsData" :key="environment.latest.id">
              <a
                :href="environment.latest.metrics_path"
                :class="{ 'is-active': environment.latest.name == currentEnvironmentName }"
                class="dropdown-item"
              >
                {{ environment.latest.name }}
              </a>
            </li>
          </ul>
        </div>
      </div>
    </div>
    <graph-group
      v-for="(groupData, index) in store.groups"
      :key="index"
      :name="groupData.group"
      :show-panels="showPanels"
    >
      <component
        :is="graphComponent"
        v-for="(graphData, graphIndex) in groupData.metrics"
        :key="graphIndex"
        :graph-data="graphData"
        :hover-data="hoverData"
        :deployment-data="store.deploymentData"
        :project-path="projectPath"
        :tags-path="tagsPath"
        :show-legend="showLegend"
        :small-graph="forceSmallGraph"
      >
        <!-- EE content -->
        <template slot="additionalSvgContent" scope="{ graphDrawData }">
          <threshold-lines
            v-for="(alert, alertName) in alertData[graphData.id]"
            :key="alertName"
            :operator="alert.operator"
            :threshold="alert.threshold"
            :graph-draw-data="graphDrawData"
          />
        </template>
        <alert-widget
          v-if="alertsEndpoint && graphData.id"
          :alerts-endpoint="alertsEndpoint"
          :label="getGraphLabel(graphData)"
          :current-alerts="getQueryAlerts(graphData)"
          :custom-metric-id="graphData.id"
          :alert-data="alertData[graphData.id]"
          @setAlerts="setAlerts"
        />
      </component>
    </graph-group>
  </div>
  <empty-state
    v-else
    :selected-state="state"
    :documentation-path="documentationPath"
    :settings-path="settingsPath"
    :clusters-path="clustersPath"
    :empty-getting-started-svg-path="emptyGettingStartedSvgPath"
    :empty-loading-svg-path="emptyLoadingSvgPath"
    :empty-no-data-svg-path="emptyNoDataSvgPath"
    :empty-unable-to-connect-svg-path="emptyUnableToConnectSvgPath"
  />
</template>
