<template>
  <main class="h-screen-main relative">
    <div class="h-full relative bg-neutral-50">
      <div class="flex justify-start items-start p-4 h-full">
        <!-- tag -->
        <aside class="border-r border-neutral-300 pr-4 mr-4 h-full sticky top-0 self-start">
          <section class="px-2 space-y-2 w-56 h-full">
            <div>
              <p class="h1">{{ i18next.t("Compare.timeUsage") }}</p>
              <ul class="list-disc list-inside text-sm leading-5 pl-3">
                <li v-for="(item, index) in timeUsageData" :key="index" :class="{active: isActive === item.tagId}"
                  @click="isActive = item.tagId" class="cursor-pointer hover:text-primary"><a :href="item.tagId">
                  {{ item.label }}
                </a>
              </li>
              </ul>
            </div>
            <div>
              <p class="h1">{{ i18next.t("Compare.frequency") }}</p>
              <ul class="list-disc list-inside text-sm leading-5 pl-3">
                <li v-for="(item, index) in frequencyData" :key="index" :class="{active: isActive === item.tagId}"
                  @click="isActive = item.tagId" class="cursor-pointer hover:text-primary">
                  <a :href="item.tagId">
                    {{ item.label }}
                  </a></li>
              </ul>
            </div>
          </section>
        </aside>
        <!-- graph -->
        <article class="w-full h-full pr-2 mr-2 overflow-x-hidden overflow-y-auto scrollbar scroll-smooth">
          <section>
            <p class="h1 px-4 border-b border-neutral-900"><span class="material-symbols-outlined mr-2 align-middle">
              {{ i18next.t("Compare.schedule") }}
            </span>
              {{ i18next.t("Compare.timeUsage") }}
            </p>
            <ul class="list-disc list-inside px-4 pl-7 text-sm">
              <li id="cycleTime" class="scroll-smooth">
                <span class="inline-block py-4">{{ i18next.t("Compare.cycleEfficiency") }}</span>
                <ul>
                  <li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{  contentData.avgCycleTime.title }}
                    </span>
                    <Chart type="line" :data="avgCycleTimeData" :options="avgCycleTimeOptions" class="h-96" />
                  </li>
                  <li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.avgCycleEfficiency.title }}
                      <span class="material-symbols-outlined align-middle ml-2 cursor-pointer !text-base"
                        v-tooltip.bottom="tooltip.avgCycleEfficiency">
                        {{ i18next.t("Compare.info") }}
                      </span>
                    </span>
                    <Chart type="bar" :data="avgCycleEfficiencyData" :options="avgCycleEfficiencyOptions" class="h-96" />
                  </li>
                </ul>
              </li>
              <li id="processingTime">
                <span class="inline-block py-4 text-sm">{{ i18next.t("Compare.ProcessingTime") }}</span>
                <ul>
                  <li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.avgProcessTime.title }}
                    </span>
                    <Chart type="line" :data="avgProcessTimeData" :options="avgProcessTimeOptions" class="h-96" />
                  </li>
                  <li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.avgProcessTimeByTask.title }}
                    </span>
                    <Chart type="bar" :data="avgProcessTimeByTaskData" :options="avgProcessTimeByTaskOptions"
                      class="h-[500px]"
                      :style="{ height: avgProcessTimeByTaskHeight }"/>
                  </li>
                </ul>
              </li>
              <li id="waitingTime">
                <span class="inline-block py-4 text-sm">{{ i18next.t("Compare.WaitingTime") }}</span>
                <ul>
                  <li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.avgWaitingTime.title }}
                      <span class="material-symbols-outlined align-middle ml-2 cursor-pointer !text-base"
                      v-tooltip.bottom="tooltip.avgWaitingTime">
                      info
                    </span></span>
                    <Chart type="line" :data="avgWaitingTimeData" :options="avgWaitingTimeOptions" class="h-96" />
                  </li>
                  <li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.avgWaitingTimeByEdge.title }}
                      <span class="material-symbols-outlined align-middle ml-2 cursor-pointer !text-base"
                      v-tooltip.bottom="tooltip.avgWaitingTimeByEdge">{{ i18next.t("Compare.info") }}</span></span>
                    <div>
                      <Chart v-if="avgWaitingTimeByEdgeData !== null" type="bar" :data="avgWaitingTimeByEdgeData"
                      :options="avgWaitingTimeByEdgeOptions" :style="{ height: avgWaitingTimeByEdgeHeight }" class="h-[500px]" />
                      <div v-else class="h-96 bg-neutral-100 m-4 flex">
                        <p class="h2 text-danger m-auto">{{ i18next.t("Compare.NoWaitingTime") }}</p>
                      </div>
                    </div>
                  </li>
                </ul>
              </li>
            </ul>
          </section>
          <section>
            <p class="h1 px-4 border-b border-neutral-900 mt-2"><span class="material-symbols-outlined mr-2 align-middle">
              {{i18next.t("Compare.moving")}}
            </span>
              {{ i18next.t("Compare.frequency") }}
            </p>
            <ul class="list-disc list-inside px-4 pl-7 text-sm">
              <li id="cases">
                <span class="inline-block py-4">{{ i18next.t("Compare.NumberOfCases") }}</span>
                <ul>
                  <li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">{{ contentData.freq.title }}</span>
                    <!-- UNUSED <Chart type="line" :data="freqData" :options="freqOptions" class="h-96" /> -->
                    <FreqChart v-if="compareDashboardData" :chartData="compareDashboardData?.freq?.cases" :content="contentData?.freq" yUnit="count"
                      pageName='Compare'
                    />
                  </li>
                  <li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
                    <span class="block font-bold text-sm leading-loose text-center my-2">
                      {{ contentData.casesByTask.title }}
                    </span>
                    <Chart type="bar" :data="casesByTaskData" :options="casesByTaskOptions" :style="{ height: casesByTaskHeight }"
                    class="h-[500px]"/>
                  </li>
                </ul>
              </li>
            </ul>
          </section>
        </article>
        <!-- Sidebar: State -->
        <div class="bg-transparent z-10">
          <ul class="flex flex-col justify-center items-center">
            <li class="inline-flex items-center justify-center border border-neutral-500  rounded-full w-9 h-9 
            cursor-pointer bg-neutral-50 drop-shadow hover:border-primary" @click="sidebarState = !sidebarState" 
            :class="{'border-primary': sidebarState}" id="compareState">
              <span class="material-symbols-outlined !text-2xl text-neutral-500 hover:text-primary p-1.5" 
              :class="[sidebarState ? 'text-primary' : 'text-neutral-500']">
                info
              </span>
            </li>
          </ul>
        </div>
        <SidebarStates v-model:visible="sidebarState"></SidebarStates>
      </div>
    </div>
  </main>
</template>
<script>
import { storeToRefs } from 'pinia';
import LoadingStore from '@/stores/loading.js';
import CompareStore from '@/stores/compare.js';
import SidebarStates from '@/components/Compare/SidebarStates.vue';
import { setLineChartData } from '@/module/setChartData.js';
import { simpleTimeLabel, followTimeLabel, getDateLabelByMinMaxDate,
  setTimeStringFormatBaseOnTimeDifference,
  mapTimestampToAxisTicksByFormat,
  getStepSizeOfYTicks,
  getYTicksByIndex,
 } from '@/module/timeLabel.js';
import i18next from '@/i18n/i18n';
import {
  knownLayoutChartOption,
  knownScaleLineChartOptions,
  knownScaleHorizontalChartOptions,
  knownScaleBarChartOptions,
 } from "@/constants/constants.js";
import FreqChart from '../../Discover/Performance/FreqChart.vue';


export default {
  setup() {
    const loadingStore = LoadingStore();
    const compareStore = CompareStore();
    const { isLoading } = storeToRefs(loadingStore);
    const { compareDashboardData } = storeToRefs(compareStore);

    return { isLoading, compareStore, compareDashboardData }
  },
  components: {
    SidebarStates,
    FreqChart,
  },
  data() {
    return {
      i18next: i18next,
      timeUsageData: [
        {tagId: '#cycleTime', label: i18next.t("Compare.cycleEfficiency")},
        {tagId: '#processingTime', label: i18next.t("Compare.ProcessingTime")},
        {tagId: '#waitingTime', label: i18next.t("Compare.WaitingTime")},
      ],
      frequencyData: [
        {tagId: '#cases', label: i18next.t("Compare.NumberOfCases")},
        // {tagId: '#trace', label: 'Number of Trace'},
        // {tagId: '#resource', label: 'Resource'},
      ],
      contentData: {
        avgCycleTime: {title: i18next.t("Compare.avgCycleTimeTitle"), x: i18next.t("Compare.labelDateX"),
          y: i18next.t("Compare.avgCycleTimeY")},
        avgCycleEfficiency: {title: i18next.t("Compare.avgCycleEfficiencyTitle"), x: i18next.t("Compare.labelDateX"),
          y: i18next.t("Compare.avgCycleEfficiencyY")},
        avgProcessTime: {title: i18next.t("Compare.avgProcessTimeTitle"), x: i18next.t("Compare.labelDateX"),
          y: i18next.t("Compare.avgProcessTimeY")},
        avgProcessTimeByTask: {title: i18next.t("Compare.avgProcessTimeByTaskTitle"),
          x: i18next.t("Compare.avgProcessTimeByTaskX"), y: i18next.t("Compare.labelActivityY")},
        avgWaitingTime: {title: i18next.t("Compare.avgWaitingTimeTitle"), x: i18next.t("Compare.labelDateX"),
          y: i18next.t("Compare.avgWaitingTimeY")},
        avgWaitingTimeByEdge: {title: i18next.t("Compare.avgWaitingTimeByEdgeTitle"),
          x: i18next.t("Compare.avgWaitingTimeByEdgeX"),
          y: i18next.t("Compare.avgWaitingTimeByEdgeY")},
        freq: {title: i18next.t("Compare.freqTitle"), x: i18next.t("Compare.labelDateX"), y: i18next.t("Compare.freqY")},
        casesByTask: {title: i18next.t("Compare.casesByTaskTitle"), x: i18next.t("Compare.casesByTaskX"),
          y: i18next.t("Compare.labelActivityY")},
      },
      tooltip: {
        avgCycleEfficiency: {
          value: i18next.t("Compare.avgCycleEfficiency"),
          class: '!max-w-[212px] !text-[10px] !opacity-80',
          autoHide: false,
        },
        avgWaitingTime: {
          value: i18next.t("Compare.avgWaitingTime"),
          class: '!max-w-[212px] !text-[10px] !opacity-80',
          autoHide: false,
        },
        avgWaitingTimeByEdge: {
          value: i18next.t("Compare.avgWaitingTimeByEdge"),
          class: '!max-w-[212px] !text-[10px] !opacity-80',
          autoHide: false,
        },
      },
      isActive: null,
      avgCycleTimeData: null,
      avgCycleTimeOptions: null,
      avgCycleEfficiencyData: null,
      avgCycleEfficiencyOptions: null,
      avgProcessTimeData: null,
      avgProcessTimeOptions: null,
      avgProcessTimeByTaskData: null,
      avgProcessTimeByTaskOptions: null,
      avgWaitingTimeData: null,
      avgWaitingTimeOptions: null,
      avgWaitingTimeByEdgeData: null,
      avgWaitingTimeByEdgeOptions: null,
      freqData: null,
      freqOptions: null,
      casesByTaskData: null,
      casesByTaskOptions: null,
      horizontalBarHeight: 500, // horizontal Bar default height
      avgProcessTimeByTaskHeight: 500,
      avgWaitingTimeByEdgeHeight: 500,
      casesByTaskHeight: 500,
      colorPrimary: '#0099FF',
      colorSecondary: '#FFAA44',
      sidebarState: false, // SideBar: Summary
    }
  },
  methods: {
    /**
     * 手刻折線圖 x label 時間刻度
     * @param { object } valueData {min: '2022-02-20T19:54:12', max: '2023-11-27T07:21:53'}
     */
    setXLabelsData(valueData) {
      let min = new Date(valueData.min).getTime();
      let max = new Date(valueData.max).getTime();
      let numPoints = 12;
      let step = (max - min) / (numPoints - 1);
      let data = [];
      for(let i = 0; i< numPoints; i++) {
        const x = min + i * step;
        data.push(x);
      }
      return data;
    },
    /**
     * 讓長條圖依 data 數量增加高度
     * @param { object } chartData chart data
     */
    getHorizontalBarHeight(chartData) {
      const totalBars = chartData.x_axis.labels.length;
      let horizontalBar = this.horizontalBarHeight;

      if(totalBars > 10){
        horizontalBar = (totalBars - 10) * 16 * 2 + this.horizontalBarHeight
      };

      return horizontalBar + 'px'
    },
    /**
     * 建立折線圖
     * @param { object } chartData chart data
     * @param { object } content titels 標題文字
     * @param { string } yUnit y 軸單位 'date' | 'count'，可傳入以上任一。
     * @returns { [primeVueSetData, primeVueSetOption] } 這兩者為符合 primeVue 圖表格式的數據資料
     */
    getLineChart(chartData, content, yUnit) {
      let datasetsPrimary;
      let datasetsSecondary;
      let minX = chartData.x_axis.min;
      let maxX = chartData.x_axis.max;
      let maxY = chartData.y_axis.max;
      let xLabelData;
      let labelPrimary = chartData.data[0].label;
      let labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};
      const getMoment = (time)=> {
        return this.$moment(time).format('YYYY/M/D hh:mm:ss')
      };
      const getSimpleTimeLabel = simpleTimeLabel;
      const getFollowTimeLabel = followTimeLabel;

      // fabricate x label according to y unit
      switch (yUnit) {
        case 'date':
          datasetsPrimary = setLineChartData(chartData.data[0].data, chartData.x_axis.max, chartData.x_axis.min, false,
          chartData.y_axis.max, chartData.y_axis.min);
          datasetsSecondary = setLineChartData(chartData.data[1].data, chartData.x_axis.max, chartData.x_axis.min, false,
          chartData.y_axis.max, chartData.y_axis.min);
          xLabelData = this.setXLabelsData(chartData.x_axis);
          break;
        case 'count': // 次數 10 個點
          datasetsPrimary = chartData.data[0].data;
          datasetsSecondary = chartData.data[1].data;
          xLabelData = chartData.data[0].data.map(item => new Date(item.x).getTime());
          break;
      }

      // Customize X axis ticks due to different differences between min and max of data group
      // Compare page and Performance page share the same logic
      const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX);
      const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xLabelData, formatToSet);
      const customizedScaleOption = this.getCustomizedScaleOption(
        knownScaleLineChartOptions, {
          customizeOptions: {
            content, ticksOfXAxis,
          }        
      });

      primeVueSetData = {
        labels: xLabelData,
        datasets: [
          {
            label: labelPrimary,
            data: datasetsPrimary,
            fill: false,
            tension: 0, // 貝茲曲線張力
            borderColor: this.colorPrimary,
            pointBackgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: datasetsSecondary,
            fill: false,
            tension: 0, // 貝茲曲線張力
            borderColor: this.colorSecondary,
            pointBackgroundColor: this.colorSecondary,
          }
        ]
      };
      primeVueSetOption = {
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            top: 16,
            left: 8,
            right: 8,
          }
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            mode: 'index',
            titleFont: {weight: 'normal'},
            callbacks: {
              title: function(context) {
                return `${content.x}: ${getMoment(context[0].parsed.x)}`;
              },
            },
          },
          title: {
            display: false,
          },
        },
        scales: customizedScaleOption,
      };
      switch (yUnit) {
        case 'date':
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = getSimpleTimeLabel(context.parsed.y, 2);

            switch (context.datasetIndex) {
              case 0: // Primary
                return `${labelPrimary}: ${value}`;
              case 1: // Secondary
                return `${labelSecondary}: ${value}`;
            }
          };
          primeVueSetOption.scales.x.min = minX;
          primeVueSetOption.scales.x.max = maxX;
          primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
            const {resultStepSize: YTickStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length); // Stepsize only needs to be calculated once
            return getYTicksByIndex(YTickStepSize, index, unitToUse); 
          }
          break;
        case 'count':
          primeVueSetOption.scales.y.ticks.precision = 0; // y 軸顯示小數點後 0 位
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = context.parsed.y;

            switch (context.datasetIndex) {
              case 0: // Primary
                return `${labelPrimary}: ${value}`;
              case 1: // Secondary
                return `${labelSecondary}: ${value}`;
            }
          };
          break;
      }
      
      // JSON.parse(JSON.stringify()) wouldn't work
      return [primeVueSetData, primeVueSetOption];
    },
    /**
     * 建立長條圖
     * @param { object } chartData chart data
     * @param { object } content titles 文字標題
     */
    getBarChart(chartData, content, caller) {
      const maxX = chartData.x_axis.max;
      const minX = chartData.x_axis.min;
      const getMoment = (time)=> this.$moment(time).format('YYYY/MM/DD');
      const getDateLabel = getDateLabelByMinMaxDate;
      let datasetsPrimary = chartData.data[0].data;
      let xDataPrimary;
      let yDataPrimary;
      let labelPrimary = chartData.data[0].label;
      let datasetsSecondary = chartData.data[1].data;
      let xDataSecondary;
      let yDataSecondary;
      let labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};

      // 轉為百分比
      datasetsPrimary = datasetsPrimary.map(value => {
        return {
          x: getMoment(value.x),
          y: value.y === null ? null : value.y * 100
        }
      });
      xDataPrimary = datasetsPrimary.map(i => i.x);
      yDataPrimary = datasetsPrimary.map(i => i.y);
      datasetsSecondary = datasetsSecondary.map(value => {
        return {
          x: getMoment(value.x),
          y: value.y === null ? null : value.y * 100
        }
      });
      xDataSecondary = datasetsSecondary.map(i => i.x);
      yDataSecondary = datasetsSecondary.map(i => i.y);

      primeVueSetData = {
        labels: xDataPrimary,
        datasets: [
          {
            label: labelPrimary,
            data: yDataPrimary,
            backgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: yDataSecondary,
            backgroundColor: this.colorSecondary,
          },
        ]
      };
      primeVueSetOption = {
        responsive: true,
        maintainAspectRatio: false,
        layout: knownLayoutChartOption,
        interaction: {
          intersect: false,
          mode: 'index', // 可顯示全部的 data label
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            titleFont: {weight: 'normal'},
            callbacks: {
              title: function(context) {
                return `${content.x}: ${context[0].label}`;
              },
              label: function(context) {
                let value = context.parsed.y;

                value = context.parsed.y === 0 ? 0 :
                    context.parsed.y === null ? "n/a" :
                    context.parsed.y.toFixed(2);
                switch (context.datasetIndex) {
                  case 0: // Primary
                    return `${labelPrimary}: ${value}`;
                  case 1: // Secondary
                    return `${labelSecondary}: ${value}`;
                }
              }
            },
          },
          title: {
            display: false,
          },
        },
        scales: this.customizeScaleChartOptionTitleByContent(knownScaleBarChartOptions, content),
      };

      if(caller === "Cycle Eff") { //針對 cycle efficiency 特別處理
        primeVueSetOption.scales.y.reverse = true; //不明原因上下顛倒，所以要顛倒過來
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          return 10 * index; //百分比
        }
      }

      return [primeVueSetData, primeVueSetOption]
    },
    /**
     * 建立水平長條圖
     * @param { object } chartData chart data
     * @param { object } content titels 標題的文字
     * @param { boolean } isSingle 單個或雙數 activity
     * @param { string } xUnit x 軸單位 'date' | 'count'，可傳入以上任一。
     */
    getHorizontalBarChart(chartData, content, isSingle, xUnit) {
      const maxY = chartData.y_axis.max;
      const getSimpleTimeLabel = simpleTimeLabel;
      const getFollowTimeLabel = followTimeLabel;
      const labelPrimary = chartData.data[0].label;
      const labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};

      // 大到小排序: Primary 為主
      const datasetsPrimary = chartData.data[0].data;
      const datasetsSecondary = chartData.data[1].data;
      datasetsPrimary.sort((a, b) => b.y - a.y);
      datasetsSecondary.sort((a, b) => {
          // Find the index of a.x in data1
          let indexA = datasetsPrimary.findIndex(item => item.x === a.x);
          // Find the index of b.x in data1
          let indexB = datasetsPrimary.findIndex(item => item.x === b.x);

          // Compare the indexes
          return indexA - indexB;
      });

      // 找出排序後，分別拉出 x, y Data
      const xLabelData = datasetsPrimary.map(item => item.x);
      const yDataPrimary = datasetsPrimary.map(item => item.y);
      const yDataSecondary = datasetsSecondary.map(item => item.y);

      primeVueSetData = {
        labels: xLabelData,
        datasets: [
          {
            label: labelPrimary,
            data: yDataPrimary,
            backgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: yDataSecondary,
            backgroundColor: this.colorSecondary,
          },
        ]
      };
      primeVueSetOption = {
        indexAxis: 'y',
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            top: 16,
            left: 8,
            right: 8,
          }
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            mode: 'index', // 可顯示全部的 data label
            titleFont: {weight: 'normal'},
            callbacks: {}
          },
          title: {
            display: false,
          },
        },
        scales: this.customizeScaleChartOptionTitleByContent(knownScaleHorizontalChartOptions, null),
      };
      switch (xUnit) {
        case 'date':
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = context.parsed.y;

              value = context.parsed.x === null ? "n/a" : getSimpleTimeLabel(context.parsed.x, 2);
              switch (context.datasetIndex) {
                case 0: // Primary
                  return `${labelPrimary}: ${value}`;
                case 1: // Secondary
                  return `${labelSecondary}: ${value}`;
              }
          };
          primeVueSetOption.scales.x.ticks.callback = function (value, index, ticks) {
            return getFollowTimeLabel(value, maxY, 1)
          };
          break;
        case 'count':
          primeVueSetOption.scales.x.ticks.precision = 0; // x 軸顯示小數點後 0 位
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = context.parsed.y;

              value = context.parsed.x === null ? "n/a" : context.parsed.x;
              switch (context.datasetIndex) {
                case 0: // Primary
                  return `${labelPrimary}: ${value}`;
                case 1: // Secondary
                  return `${labelSecondary}: ${value}`;
              }
          };
          break;
      }
      if(isSingle) { // 設定一個活動的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label}`;
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          if(label) {
              return label.length > 21 ? `${label.substring(0, 18)}...` : label
            };
          }
          
      }else { // 設定「活動」到「活動」的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label.replace(',', ' - ')}`
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          let labelStart = label[0];
          let labelEnd = label[1];

          labelStart = labelStart.length > 10 ? `${labelStart.substring(0,7)}...` : labelStart;
          labelEnd = labelEnd.length > 10 ? `${labelEnd.substring(0,7)}...` : labelEnd;
          return labelStart + " - " + labelEnd
        };
      }

      return [primeVueSetData, primeVueSetOption]
    },
    /**
     * 
     * @param whichScaleObj PrimeVue scale option object to reference to
     * @param customizeOptions 
     * @param customizeOptions.content
     * @param customizeOptions.ticksOfXAxis
     */
    getCustomizedScaleOption(whichScaleObj, {customizeOptions: {
          content,
          ticksOfXAxis,
        },
      }) {
      let resultScaleObj;
      resultScaleObj = this.customizeScaleChartOptionTitleByContent(whichScaleObj, content);
      resultScaleObj = this.customizeScaleChartOptionTicks(resultScaleObj, ticksOfXAxis);
      return resultScaleObj;
    },
    /**
     * 在一個基本的物件上加以客製化這個物件，客製化的參照來源是 content 的內容
     * 之所以有辦法這樣撰寫，是因為我們知道物件的順序是先 x 再 title 再 text
     * This function alters the title property of known scales object of Chart option
     * This is based on the fact that we know the order must be x -> title -> text.
     * @param {object} whichScaleObj PrimeVue scale option object to reference to
     * @param content whose property includes x and y and stand for titles
     * 
     * @returns { object } an object modified with two titles
     */
    customizeScaleChartOptionTitleByContent(whichScaleObj, content){
      if (!content) {
        // Early return
        return whichScaleObj;
      }

      return {
        ...whichScaleObj,
          x: {
            ...whichScaleObj.x,
            title: {
              ...whichScaleObj.x.title,
              text: content.x
            }
          },
          y: {
            ...whichScaleObj.y,
            title: {
              ...whichScaleObj.y.title,
              text: content.y
            }
          }
        };
    },
    /**
     * 
     * @param {object} scaleObjectToAlter this object follows the format of prive vue chart
     * @param {Array<string>} ticksOfXAxis For example, ['05/06', '05,07', '05/08']
     * or ['08:03:01', '08:11:18', '09:03:41', ], and so on.
     */
     customizeScaleChartOptionTicks(scaleObjectToAlter, ticksOfXAxis) {
      return {
        ...scaleObjectToAlter,
        x: {
          ...scaleObjectToAlter.x,
            ticks: {
              ...scaleObjectToAlter.x.ticks,
                callback: function(value, index) {
                  // 根據不同的級距客製化 x 軸的時間刻度
                  return ticksOfXAxis[index];
                },
            },
          },
      };       
    },
    /**
     * 建立Compare頁面的折線圖，並且避免同一個畫面中的設定值彼此覆蓋
     * @param { object } chartData chart data
     * @param { object } content titels 標題文字
     * @param { string } yUnit y 軸單位 'date' | 'count'，可傳入以上任一。
     * @returns { [primeVueSetData, primeVueSetOption] } 這兩者為符合 primeVue 圖表格式的數據資料
     */
     getLineChart(chartData, content, yUnit) {
      let datasetsPrimary;
      let datasetsSecondary;
      let minX = chartData.x_axis.min;
      let maxX = chartData.x_axis.max;
      let maxY = chartData.y_axis.max;
      let xLabelData;
      let labelPrimary = chartData.data[0].label;
      let labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};
      const getMoment = (time)=> {
        return this.$moment(time).format('YYYY/M/D hh:mm:ss')
      };
      const getSimpleTimeLabel = simpleTimeLabel;
      const getFollowTimeLabel = followTimeLabel;

      // fabricate x label according to y unit
      switch (yUnit) {
        case 'date':
          datasetsPrimary = setLineChartData(chartData.data[0].data, chartData.x_axis.max, chartData.x_axis.min, false,
          chartData.y_axis.max, chartData.y_axis.min);
          datasetsSecondary = setLineChartData(chartData.data[1].data, chartData.x_axis.max, chartData.x_axis.min, false,
          chartData.y_axis.max, chartData.y_axis.min);
          xLabelData = this.setXLabelsData(chartData.x_axis);
          break;
        case 'count': // 次數 10 個點
          datasetsPrimary = chartData.data[0].data;
          datasetsSecondary = chartData.data[1].data;
          xLabelData = chartData.data[0].data.map(item => new Date(item.x).getTime());
          break;
      }

      // Customize X axis ticks due to different differences between min and max of data group
      // Compare page and Performance page share the same logic
      const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX);
      const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xLabelData, formatToSet);

      primeVueSetData = {
        labels: xLabelData,
        datasets: [
          {
            label: labelPrimary,
            data: datasetsPrimary,
            fill: false,
            tension: 0, // 貝茲曲線張力
            borderColor: this.colorPrimary,
            pointBackgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: datasetsSecondary,
            fill: false,
            tension: 0, // 貝茲曲線張力
            borderColor: this.colorSecondary,
            pointBackgroundColor: this.colorSecondary,
          }
        ]
      };
      primeVueSetOption = {
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            top: 16,
            left: 8,
            right: 8,
          }
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            mode: 'index',
            titleFont: {weight: 'normal'},
            callbacks: {
              title: function(context) {
                return `${content.x}: ${getMoment(context[0].parsed.x)}`;
              },
            },
          },
          title: {
            display: false,
          },
        },
        scales:  {
          x: {
            min: minX,
            max: maxX,
            type: 'time',
            title: {
              display: true,
              color: '#334155',
              font: {
                size: 12,
                lineHeight: 2
              },
              text: content.x,              
            },
            time: {
              displayFormats: {
                second: 'h:mm:ss', // ex: 1:11:11
                minute: 'M/d h:mm', // ex: 1/1 1:11
                hour: 'M/d h:mm', // ex: 1/1 1:11
                day: 'M/d h', // ex: 1/1 1
                month: 'y/M/d', // ex: 1911/1/1
              },
              round: true
            },
            ticks: {
              padding: 8,
              display: true,
              maxRotation: 0, // 不旋轉 lable 0~50
              color: '#64748b',
              source: 'labels', // 依比例彈性顯示 label 數量
              callback: function(value, index) {
                return ticksOfXAxis[index];
              },
            },
            border: {
              color: '#64748b',
            },
          },
          y: {
            beginAtZero: true, // scale 包含 0
            title: {
              display: true,
              color: '#334155',
              font: {
                size: 12,
                lineHeight: 2
              },
              text: content.y
            },
            grid: {
              color: '#64748b',
            },
            border: {
              display: false, // 隱藏左側多出來的線
            },
            ticks: {
              
              color: '#64748b',
              padding: 8,
              callback: function (value, index, ticks) {
                // resultStepSize: Y 軸一個刻度的高度的純數值部分，unitToUse則可能是 d,h,m,s 四者之一
                const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length);
                return getYTicksByIndex(resultStepSize, index, unitToUse);
              },
            }
          },
        },
        plugins: {
          tooltip: {
            callbacks:{
              label:function(context) {
                return `${content.y}: ${getSimpleTimeLabel(context.parsed.y, 2)}`;
              },
            },
          },
        },
      };

      return [primeVueSetData, primeVueSetOption];
    },
    /**
     * 建立Case By Task水平長條圖
     * 避免共用 PrimeVue 設定值，避免覆蓋設定
     * @param { object } chartData chart data
     * @param { object } content titels 標題的文字
     * @param { boolean } isSingle 單個或雙數 activity
     * @param { string } xUnit x 軸單位
     */
     getCaseByTaskHorizontalBarChart(chartData, content, isSingle, xUnit = 'count') {
      const maxX = chartData.x_axis.max;
      const getSimpleTimeLabel = simpleTimeLabel;
      const getFollowTimeLabel = followTimeLabel;
      const labelPrimary = chartData.data[0].label;
      const labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};

      // 大到小排序: Primary 為主
      const datasetsPrimary = chartData.data[0].data;
      const datasetsSecondary = chartData.data[1].data;
      datasetsPrimary.sort((a, b) => b.y - a.y);
      datasetsSecondary.sort((a, b) => {
          // Find the index of a.x in data1
          let indexA = datasetsPrimary.findIndex(item => item.x === a.x);
          // Find the index of b.x in data1
          let indexB = datasetsPrimary.findIndex(item => item.x === b.x);

          // Compare the indexes
          return indexA - indexB;
      });

      // 找出排序後，分別拉出 x, y Data
      const xLabelData = datasetsPrimary.map(item => item.x);
      const yDataPrimary = datasetsPrimary.map(item => item.y);
      const yDataSecondary = datasetsSecondary.map(item => item.y);

      primeVueSetData = {
        labels: xLabelData,
        datasets: [
          {
            label: labelPrimary,
            data: yDataPrimary,
            backgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: yDataSecondary,
            backgroundColor: this.colorSecondary,
          },
        ]
      };
      primeVueSetOption = {
        indexAxis: 'y',
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            top: 16,
            left: 8,
            right: 8,
          }
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            mode: 'index', // 可顯示全部的 data label
            titleFont: {weight: 'normal'},
            callbacks: {}
          },
          title: {
            display: false,
          },
        },
        scales: {
          x: {
              title: {
                display: true,
                color: '#334155',
                font: {
                    size: 12,
                    lineHeight: 2
                },
                text: content.x,
              },
              ticks: {
                display: true,
                maxRotation: 0, // 不旋轉 lable 0~50
                color: '#64748b',
                callback: function(value, index, ticks) {
                  return value; // 計算數量，沒有時間單位才對
                }
                },
              grid: {
              color: '#64748b',
              tickLength: 0, // 網格是否超過邊線
              },
              border: {
              display:false,
              },
          },
          y: {
              beginAtZero: true, // scale 包含 0
              type: 'category',
              title: {
                display: true,
                color: '#334155',
                font: {
                    size: 12,
                    lineHeight: 2
                },
                text: content.y,
              },
              ticks:{
              color: '#64748b',
              padding: 8,
              },
              grid: {
              display:false,
              color: '#64748b',
              },
              border: {
              display: false, // 隱藏左側多出來的線
              },
          },
          },
      };
      switch (xUnit) {
        case 'count':
        default:
          primeVueSetOption.scales.x.ticks.precision = 0; // x 軸顯示小數點後 0 位
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = context.parsed.y;

              value = context.parsed.x === null ? "n/a" : context.parsed.x;
              switch (context.datasetIndex) {
                case 0: // Primary
                  return `${labelPrimary}: ${value}`;
                case 1: // Secondary
                  return `${labelSecondary}: ${value}`;
              }
          };
          break;
      }
      if(isSingle) { // 設定一個活動的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label}`;
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          if(label) {
              return label.length > 21 ? `${label.substring(0, 18)}...` : label
            };
          }
          
      }else { // 設定「活動」到「活動」的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label.replace(',', ' - ')}`
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          let labelStart = label[0];
          let labelEnd = label[1];

          labelStart = labelStart.length > 10 ? `${labelStart.substring(0,7)}...` : labelStart;
          labelEnd = labelEnd.length > 10 ? `${labelEnd.substring(0,7)}...` : labelEnd;
          return labelStart + " - " + labelEnd
        };
      }

      return [primeVueSetData, primeVueSetOption]
    },
        /**
     * 建立 Average Processing Time水平長條圖
     * 避免共用 PrimeVue 設定值，避免覆蓋設定
     * @param { object } chartData chart data
     * @param { object } content titels 標題的文字
     * @param { boolean } isSingle 單個或雙數 activity
     * @param { string } xUnit x 軸單位 'date' | 'count'，可傳入以上任一。
     */
     getAvgProcessTimeHorizontalBarChart(chartData, content, isSingle, xUnit="date") {
      const maxY = chartData.y_axis.max;
      const getSimpleTimeLabel = simpleTimeLabel;
      const getFollowTimeLabel = followTimeLabel;
      const labelPrimary = chartData.data[0].label;
      const labelSecondary = chartData.data[1].label;
      let primeVueSetData = {};
      let primeVueSetOption = {};

      // 大到小排序: Primary 為主
      const datasetsPrimary = chartData.data[0].data;
      const datasetsSecondary = chartData.data[1].data;
      datasetsPrimary.sort((a, b) => b.y - a.y);
      datasetsSecondary.sort((a, b) => {
          // Find the index of a.x in data1
          let indexA = datasetsPrimary.findIndex(item => item.x === a.x);
          // Find the index of b.x in data1
          let indexB = datasetsPrimary.findIndex(item => item.x === b.x);

          // Compare the indexes
          return indexA - indexB;
      });

      // 找出排序後，分別拉出 x, y Data
      const xLabelData = datasetsPrimary.map(item => item.x);
      const yDataPrimary = datasetsPrimary.map(item => item.y);
      const yDataSecondary = datasetsSecondary.map(item => item.y);

      primeVueSetData = {
        labels: xLabelData,
        datasets: [
          {
            label: labelPrimary,
            data: yDataPrimary,
            backgroundColor: this.colorPrimary,
          },
          {
            label: labelSecondary,
            data: yDataSecondary,
            backgroundColor: this.colorSecondary,
          },
        ]
      };
      primeVueSetOption = {
        indexAxis: 'y',
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            top: 16,
            left: 8,
            right: 8,
          }
        },
        plugins: {
          legend: false, // 圖例
          tooltip: {
            // displayColors: false,
            mode: 'index', // 可顯示全部的 data label
            titleFont: {weight: 'normal'},
            callbacks: {}
          },
          title: {
            display: false,
          },
        },
        scales: {
        x: {
            title: {
              display: true,
              color: '#334155',
              font: {
                  size: 12,
                  lineHeight: 2
              },
              text: content.x,
            },
            ticks: {
            display: true,
            maxRotation: 0, // 不旋轉 lable 0~50
            color: '#64748b',
            },
            grid: {
            color: '#64748b',
            tickLength: 0, // 網格是否超過邊線
            },
            border: {
            display:false,
            },
        },
        y: {
            beginAtZero: true, // scale 包含 0
            type: 'category',
            title: {
              display: true,
              color: '#334155',
              font: {
                  size: 12,
                  lineHeight: 2
              },
              text: content.y
            },
            ticks:{
            color: '#64748b',
            padding: 8,
            },
            grid: {
            display:false,
            color: '#64748b',
            },
            border: {
            display: false, // 隱藏左側多出來的線
            },
          },
        },
      };
      switch (xUnit) {
        case 'date':
        default:
          primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
            let value = context.parsed.y;

              value = context.parsed.x === null ? "n/a" : getSimpleTimeLabel(context.parsed.x, 2);
              switch (context.datasetIndex) {
                case 0: // Primary
                  return `${labelPrimary}: ${value}`;
                case 1: // Secondary
                  return `${labelSecondary}: ${value}`;
              }
          };
          primeVueSetOption.scales.x.ticks.callback = function (value, index, ticks) {
            return getFollowTimeLabel(value, maxY, 1)
          };
          break;
      }
      if(isSingle) { // 設定一個活動的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label}`;
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          if(label) {
              return label.length > 21 ? `${label.substring(0, 18)}...` : label
            };
          }
          
      }else { // 設定「活動」到「活動」的 y label、提示框文字
        primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
          return `${content.y}: ${context[0].label.replace(',', ' - ')}`
        };
        primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
          let label = xLabelData[index];
          let labelStart = label[0];
          let labelEnd = label[1];

          labelStart = labelStart.length > 10 ? `${labelStart.substring(0,7)}...` : labelStart;
          labelEnd = labelEnd.length > 10 ? `${labelEnd.substring(0,7)}...` : labelEnd;
          return labelStart + " - " + labelEnd
        };
      }

      return [primeVueSetData, primeVueSetOption]
    },
  },
  async created() {
    this.isLoading = true; // moubeted 才停止 loading

    const routeParams = this.$route.params;
    const primaryType = routeParams.primaryType;
    const secondaryType = routeParams.secondaryType;
    const primaryId = routeParams.primaryId;
    const secondaryId = routeParams.secondaryId;
    const typeMap = {
      'log': 'log_id',
      'filter': 'filter_id'
    };
    const primaryTypeParam = typeMap[primaryType];
    const secondaryTypeParam = typeMap[secondaryType];
    const queryParams = [
      { [primaryTypeParam]: primaryId },
      { [secondaryTypeParam]: secondaryId }
    ];

    // 取得 Compare Data
    await this.compareStore.getCompare(queryParams);
    this.avgProcessTimeByTaskHeight = await this.getHorizontalBarHeight(this.compareDashboardData.time.avg_process_time_by_task);
    if(this.compareDashboardData.time.avg_waiting_time_by_edge !== null) {
      this.avgWaitingTimeByEdgeHeight = await this.getHorizontalBarHeight(this.compareDashboardData.time.avg_waiting_time_by_edge);
    };
    this.casesByTaskHeight = await this.getHorizontalBarHeight(this.compareDashboardData.freq.cases_by_task);
    // create chart
    [this.avgCycleTimeData, this.avgCycleTimeOptions] = this.getLineChart(
      this.compareDashboardData.time.avg_cycle_time, this.contentData.avgCycleTime, 'date');
    [this.avgCycleEfficiencyData, this.avgCycleEfficiencyOptions] = this.getBarChart(
      this.compareDashboardData.time.avg_cycle_efficiency, this.contentData.avgCycleEfficiency, "Cycle Eff");
    [this.avgProcessTimeData, this.avgProcessTimeOptions] = this.getLineChart(
      this.compareDashboardData.time.avg_process_time, this.contentData.avgProcessTime, 'date');
    [this.avgProcessTimeByTaskData, this.avgProcessTimeByTaskOptions] = this.getAvgProcessTimeHorizontalBarChart(
      this.compareDashboardData.time.avg_process_time_by_task,
      this.contentData.avgProcessTimeByTask, true, 'date');
    [this.avgWaitingTimeData, this.avgWaitingTimeOptions] = this.getLineChart(
      this.compareDashboardData.time.avg_waiting_time, this.contentData.avgWaitingTime, 'date');
    if(this.compareDashboardData.time.avg_waiting_time_by_edge !== null) {
      [this.avgWaitingTimeByEdgeData, this.avgWaitingTimeByEdgeOptions] = this.getHorizontalBarChart(
        this.compareDashboardData.time.avg_waiting_time_by_edge,
        this.contentData.avgWaitingTimeByEdge, false, 'date');
    } else {
      [this.avgWaitingTimeByEdgeData, this.avgWaitingTimeByEdgeOptions] = [null, null]
    }
    [this.freqData, this.freqOptions] = this.getLineChart(
      this.compareDashboardData.freq.cases, this.contentData.freq, 'count');
    [this.casesByTaskData, this.casesByTaskOptions] = this.getCaseByTaskHorizontalBarChart(
      this.compareDashboardData.freq.cases_by_task, this.contentData.casesByTask, true, 'count');
  },
  mounted() {
    // 停止 loading
    this.isLoading = false;
  }
}
</script>
<style scoped>
.active {
  @apply text-primary
}
</style>
