<template>
  <div class="panel-box2" :class="{'panel-box2--entity-detail': entity && entity.entityType}">
    <div class="panel__header" v-if="!entity">
      <div class="panel__title">{{panelName?panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}}
        <div v-if="showScore" class="score">
          <div class="circle-icon"  v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
          <div class="circle-icon"  v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
          <div class="circle-icon"  v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
          Score:{{score}}
          </div>
          <div v-if="showEntityDetail" class="panel-show-detail">
            <el-tooltip
                effect="light"
                trigger="hover"
                :content="$t('entity.jumpToEntityDetails')"
                placement="right"
                popper-class="panel-tooltip"
            >
              <i class="cn-icon cn-icon-jump-to" @click="jumpEntityDetail"></i>
            </el-tooltip>
          </div>
      </div>
      <div class="panel__tools">
        <el-select
            size="mini"
            v-model="metric"
            placeholder=" "
            popper-class="common-select"
            v-if="showMetric"
            :popper-append-to-body="false"
            @change="metricChange"
        >
          <template #prefix>
            <span class="select-prefix">Metric:</span>
          </template>
          <el-option v-for="item in metricOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
        </el-select>
        <div class="panel__time">
          <date-time-range
              class="date-time-range"
              :start-time="timeFilter.startTime"
              :end-time="timeFilter.endTime"
              :date-range="timeFilter.dateRangeValue"
              ref="dateTimeRange"
              @change="reload"
          />
          <time-refresh
              class="date-time-range"
              @change="timeRefreshChange"
              :end-time="timeFilter.endTime"
          />
        </div>
      </div>
    </div>
    <chart-list
        ref="chartList"
        :time-filter="timeFilter"
        :metric="metric"
        :chart-list="chartList"
        :panel-type="panelType"
        :panel-lock="panelLock"
        :extra-params="extraParams"
        :entity="entity"
    ></chart-list>
  </div>
</template>

<script>
import { useRoute } from 'vue-router'
import { ref } from 'vue'
import {
  panelTypeAndRouteMapping,
  curTabState,
  drillDownPanelTypeMapping,
  metricOptions,
  fromRoute
} from '@/utils/constants'
import { getPanelList, getChartList, api } from '@/utils/api'
import { getNowTime, getSecond } from '@/utils/date-util'
import { getTypeCategory } from '@/views/charts/charts/tools'
import { urlParamsHandler, overwriteUrl, getDnsMapData, computeScore } from '@/utils/tools'
import ChartList from '@/views/charts2/ChartList'
import { useStore } from 'vuex'
import axios from 'axios'
import _ from 'lodash'

export default {
  name: 'Panel',
  props: {
    entity: Object,
    typeName: String
  },
  components: {
    ChartList
  },
  data () {
    return {
      panelTypeAndRouteMapping,
      metricOptions,
      chartList: [], // 普通panel的chart
      panelLock: true,
      extraParams: {},
      panelName: '',
      dnsRcodeMapData: [],
      dnsQtypeMapData: [],
      score: null,
      curTabState: curTabState,
      performanceData: {},
      scoreDataState: false // 评分数据是否加载完成
    }
  },
  computed: {
    // npmThirdLevelMenuScore () {
    //   return this.$store.getters.getNpmThirdLevelMenuScore
    // }
    // 显示顶部的Metric单位选项标识
    showMetric () {
      return this.panelType === panelTypeAndRouteMapping.networkOverview || this.panelType === panelTypeAndRouteMapping.networkOverviewDrillDown
    },
    scoreBaseState () {
      return this.$store.getters.scoreBaseReady
    }
  },
  watch: {
    timeFilter: {
      handler () {
        if (this.$route.path === '/panel/networkAppPerformance') {
          this.$store.commit('resetScoreBase')
          this.queryScoreBase()
          if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
            this.scoreCalculation()
          }
        }
      }
    },
    scoreBaseState (n) {
      if (n && this.scoreDataState) {
        this.handleScoreData()
      }
    },
    scoreDataState (n) {
      if (n && this.scoreBaseState) {
        this.handleScoreData()
      }
    }
  },
  async mounted () {
    // this.panelName = this.$store.getters.getPanelName
    const pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : ''
    const curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
    if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
      this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
      this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
      this.$store.commit('setDnsQtypeMapData', this.dnsQtypeMapData)
      this.$store.commit('setDnsRcodeMapData', this.dnsRcodeMapData)
    }
    if (curTabProp === 'qtype') {
      this.panelName = this.dnsQtypeMapData.get(pName)
    } else if (curTabProp === 'rcode') {
      this.panelName = this.dnsRcodeMapData.get(pName)
    } else {
      this.panelName = pName
    }

    // const curOperationType = this.$store.getters.getTabOperationType
    /* const curOperationType = this.getUrlParam(this.curTabState.tabOperationType, '', true)
    if (this.panelName && this.$route.path === '/panel/networkAppPerformance' && curOperationType !== operationType.thirdMenu) {
      // const columnValue = this.$store.getters.getBreadcrumbColumnValue
      const columnValue = this.getUrlParam(this.curTabState.fourthMenu, '')
      const queryParams = {
        startTime: getSecond(this.timeFilter.startTime),
        endTime: getSecond(this.timeFilter.endTime),
        // type: this.$store.getters.getDimensionType,
        type: this.$route.query.dimensionType ? this.$route.query.dimensionType : '',
        params: columnValue || ''
      }
      const requestGroup = []
      scoreUrl.forEach(url => {
        if (url) {
          const request = get(url, queryParams, true)
          requestGroup.push(request)
        }
      })
      const scoreGroup = []
      let score = 0
      Promise.all(requestGroup).then(res => {
        res.forEach(t => {
          if (t.code === 200) {
            const data = t.data.result ? t.data.result[0] : null
            if (data) {
              customTableTitlesForAppPerformance.forEach(item => {
                if (data[bytesColumnNameGroupForNpm[item.prop]]) {
                  score = computeScore(data, item.scoreType)
                  scoreGroup.push(score)
                } else {
                  scoreGroup.push(0)
                }
              })
            }
          }
        })
      }).finally(() => {
        scoreGroup.forEach(i => {
          score = Number(score) + Number(i)
        })
        score = Math.ceil(score * 6)
        if (score > 6) {
          score = 6
        }
        this.score = score || 0
      })
    } else if (this.$route.path === '/panel/networkAppPerformance' && curOperationType === operationType.thirdMenu) {
      this.score = this.$store.getters.getNpmThirdLevelMenuScore
    } */

    await this.init()
    const vm = this
    this.emitter.on('reloadChartList', async function () {
      vm.chartList = []
      vm.chartList = (await getChartList({ panelId: vm.panel.id, pageSize: -1 })).map(chart => {
        chart.i = chart.id
        // 递归初始化各属性
        vm.initChartAttr(chart)
        return chart
      })
    })
    if (this.$route.path === '/panel/networkAppPerformance') {
      if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
        this.scoreCalculation()
      }
    }
    if (this.$route.path === '/panel/networkAppPerformance' || this.$route.path === '/panel/linkMonitor') {
      this.$store.commit('resetScoreBase')
      this.queryScoreBase()
    }
  },
  setup (props) {
    // router引入store会报错，故在panel里调用
    const store = useStore()
    const cancelList = store.state.panel.httpCancel

    // 进入页面时，发现有未结束的请求，终止请求
    if (cancelList.length > 0) {
      cancelList.forEach((cancel, index) => {
        cancel()
        delete cancelList[index]
      })
    }

    const panel = ref({})
    let panelType = 1 // 取得panel的type
    let { params, query, path } = useRoute()

    // 获取路由跳转过的历史状态，赋值给当前界面，起到保留状态的作用，如浏览器的回退前进等
    const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t)
    if (routerObj) {
      params = routerObj.params
      query = routerObj.query
      path = routerObj.path

      // 如果当前界面之前载入过，获取状态后更新地址栏，以便后续的赋值操作
      const newUrl = urlParamsHandler(window.location.href, useRoute().query, query)
      overwriteUrl(newUrl)
    }

    const thirdPanel = query.thirdPanel
    const fourthPanel = query.fourthPanel
    const entityType = ref('')
    const entityValue = ref('')
    const showEntityDetail = ref(false)

    if (fourthPanel) {
      // networkOverviewBeforeTab是dashboard点击下钻标识，dimensionType是详情页到下钻页标识
      const tab = query.networkOverviewBeforeTab || query.dimensionType
      const value = query.fourthMenu
      const ipList = ['ip', 'clientIp', 'serverIp', 'a', 'aaaa']
      const appList = ['appLabel']
      const domainList = ['sslSni', 'domain']

      if (ipList.indexOf(tab) > -1) {
        entityType.value = 'ip'
        showEntityDetail.value = true
      } else if (appList.indexOf(tab) > -1) {
        entityType.value = 'app'
        showEntityDetail.value = true
      } else if (domainList.indexOf(tab) > -1) {
        entityType.value = 'domain'
        showEntityDetail.value = true
      }
      entityValue.value = value
      panelType = Number(fourthPanel)
    } else if (thirdPanel) {
      panelType = Number(thirdPanel)
    } else {
      panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
    }

    // 获取url携带的range、startTime、endTime
    const rangeParam = query.range
    const startTimeParam = query.startTime
    const endTimeParam = query.endTime
    // 若url携带了，使用携带的值，否则使用默认值。

    const dateRangeValue = rangeParam ? parseInt(query.range) : 60
    const timeFilter = ref({ dateRangeValue })
    if (!startTimeParam || !endTimeParam) {
      const { startTime, endTime } = getNowTime(60)
      timeFilter.value.startTime = getSecond(startTime)
      timeFilter.value.endTime = getSecond(endTime)
      // 如果没有时间参数，就将参数写入url
      const newUrl = urlParamsHandler(window.location.href, useRoute().query, { startTime: timeFilter.value.startTime, endTime: timeFilter.value.endTime, range: dateRangeValue })
      overwriteUrl(newUrl)
    } else {
      timeFilter.value.startTime = parseInt(startTimeParam)
      timeFilter.value.endTime = parseInt(endTimeParam)
    }

    // npm是否展示分数
    const showScorePanel = [drillDownPanelTypeMapping.npmOverviewIp, drillDownPanelTypeMapping.npmOverviewDomain, drillDownPanelTypeMapping.npmOverviewApp, drillDownPanelTypeMapping.npmOverviewCommon, drillDownPanelTypeMapping.npmThirdMenu]
    const showScore = showScorePanel.indexOf(panelType) > -1

    const metric = ref(query.metric || 'Bits/s')

    const lineQueryCondition = ref(query.lineQueryCondition || '')
    const dimensionType = ref(query.dimensionType || '')
    // 三级菜单判断
    const tabOperationType = ref(query.tabOperationType)
    const networkOverviewBeforeTab = ref(query.networkOverviewBeforeTab || '')
    return {
      panelType,
      panel,
      timeFilter,
      showScore,
      metric,
      path,
      lineQueryCondition,
      dimensionType,
      tabOperationType,
      networkOverviewBeforeTab,
      showEntityDetail,
      entityType,
      entityValue
    }
  },
  methods: {
    async init () {
      const panels = await getPanelList({ type: this.panelType })
      if (panels && panels.length > 0) {
        this.panel = panels[0]
      }
      if (this.panel.id) {
        if (this.panel.params) {
          this.panel.params = JSON.parse(this.panel.params)
        } else {
          this.panel.params = {}
        }
        this.chartList = (await getChartList({ panelId: this.panel.id, pageSize: -1 })).map(chart => {
          chart.i = chart.id
          // 递归初始化各属性
          this.initChartAttr(chart)
          return chart
        })
      }
    },
    initChartAttr (chart) {
      chart.i = chart.id
      chart.category = getTypeCategory(chart.type)
      // 初始化params
      chart.params = chart.params ? JSON.parse(chart.params) : {}
      chart.firstShow = false
      if (!this.$_.isEmpty(chart.children)) {
        chart.children.forEach(c => {
          this.initChartAttr(c)
        })
      }
    },
    reload (startTime, endTime, dateRangeValue) {
      this.timeFilter = { startTime: getSecond(startTime), endTime: getSecond(endTime), dateRangeValue: dateRangeValue }
      const { query } = this.$route
      this.$store.commit('setTimeRangeArray', [this.timeFilter.startTime, this.timeFilter.endTime])
      this.$store.commit('setTimeRangeFlag', dateRangeValue.value)

      const newUrl = urlParamsHandler(window.location.href, query, {
        startTime: this.timeFilter.startTime,
        endTime: this.timeFilter.endTime,
        range: dateRangeValue.value
      })
      overwriteUrl(newUrl)
    },
    timeRefreshChange () {
      // 不是自选时间
      if (this.$refs.dateTimeRange) {
        if (!this.$refs.dateTimeRange.isCustom) {
          const value = this.timeFilter.dateRangeValue
          this.$refs.dateTimeRange.quickChange(value)
        } else {
          this.timeFilter = JSON.parse(JSON.stringify(this.timeFilter))
        }
      } else {
        this.timeFilter = JSON.parse(JSON.stringify(this.timeFilter))
      }
    },
    getUrlParam (param, defaultValue, isNumber) {
      if (isNumber) {
        return this.$route.query[param] ? Number(this.$route.query[param]) : defaultValue
      } else {
        return this.$route.query[param] ? this.$route.query[param] : defaultValue
      }
    },
    metricChange (value) {
      const { query } = this.$route
      const newUrl = urlParamsHandler(window.location.href, query, {
        metric: value
      })
      overwriteUrl(newUrl)
    },
    // 动态查询评分基准
    queryScoreBase () {
      const params = {
        startTime: this.timeFilter.startTime,
        endTime: this.timeFilter.endTime
      }
      const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
      const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
      const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
      const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
      const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
      Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
        const scoreBase = {}
        res.forEach((t, i) => {
          if (t.status === 200) {
            if (i === 0) {
              scoreBase.establishLatencyMsP10 = _.get(t.data, 'data.result.establishLatencyMsP10', null)
              scoreBase.establishLatencyMsP90 = _.get(t.data, 'data.result.establishLatencyMsP90', null)
            } else if (i === 1) {
              scoreBase.httpResponseLatencyP10 = _.get(t.data, 'data.result.httpResponseLatencyP10', null)
              scoreBase.httpResponseLatencyP90 = _.get(t.data, 'data.result.httpResponseLatencyP90', null)
            } else if (i === 2) {
              scoreBase.sslConLatencyP10 = _.get(t.data, 'data.result.sslConLatencyP10', null)
              scoreBase.sslConLatencyP90 = _.get(t.data, 'data.result.sslConLatencyP90', null)
            } else if (i === 3) {
              scoreBase.tcpLostlenPercentP10 = _.get(t.data, 'data.result.tcpLostlenPercentP10', null)
              scoreBase.tcpLostlenPercentP90 = _.get(t.data, 'data.result.tcpLostlenPercentP90', null)
            } else if (i === 4) {
              scoreBase.pktRetransPercentP10 = _.get(t.data, 'data.result.pktRetransPercentP10', null)
              scoreBase.pktRetransPercentP90 = _.get(t.data, 'data.result.pktRetransPercentP90', null)
            }
          }
        })
        this.$store.commit('setScoreBase', scoreBase)
      }).catch((e) => {
      }).finally(() => {
      })
    },
    scoreCalculation () {
      let condition = ''
      let url = ''
      if (this.lineQueryCondition.indexOf(' OR ') > -1) {
        condition = this.lineQueryCondition.split(/["|'](.*?)["|']/)
      } else if (this.lineQueryCondition.indexOf('+OR+') > -1) {
        condition = this.lineQueryCondition.replace(/\+/g, ' ').split(/["|'](.*?)["|']/)
      } else {
        condition = this.lineQueryCondition
      }
      const type = this.dimensionType || this.networkOverviewBeforeTab
      const params = {
        startTime: getSecond(this.timeFilter.startTime),
        endTime: getSecond(this.timeFilter.endTime),
        cycle: 0
      }
      if (condition && (typeof condition !== 'object') && type) {
        if (type === 'clientIp') {
          params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='client'`
        } else if (type === 'serverIp') {
          params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='server'`
        } else if (type === 'clientCity') {
          params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'`
        } else if (type === 'serverCity') {
          params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'`
        } else {
          params.q = condition
        }
        params.type = type
      } else if (condition.length > 1 && type && type === 'ip') {
        params.q = `${type}='${condition[1]}'`
        params.type = type
      } else if (condition.length > 1 && type && type !== 'ip') {
        if (type === 'country' || type === 'asn' || type === 'province' || type === 'city' || type === 'isp') {
          params.q = `${type}='${condition[1]}'`
          params.type = type
        } else {
          params.q = `${condition[0]}'${condition[1]}'`
          params.type = type
        }
      }
      if (parseFloat(this.tabOperationType) === 3) {
        url = api.npm.overview.allNetworkAnalysis
      } else {
        url = api.npm.overview.networkAnalysis
      }
      if ((type && condition) || type) {
        this.scoreDataState = false
        this.performanceData = {}
        params.type = params.type || type
        axios.get(url, { params }).then(res => {
          if (res.status === 200) {
            this.performanceData = {
              establishLatencyMs: _.get(res, 'data.data.result.establishLatencyMsAvg', null),
              httpResponseLatency: _.get(res, 'data.data.result.httpResponseLatencyAvg', null),
              sslConLatency: _.get(res, 'data.data.result.sslConLatencyAvg', null),
              tcpLostlenPercent: _.get(res, 'data.data.result.tcpLostlenPercentAvg', null),
              pktRetransPercent: _.get(res, 'data.data.result.pktRetransPercentAvg', null)
            }
          }
        }).finally(() => {
          this.scoreDataState = true
        })
      }
    },
    jumpEntityDetail () {
      const { href } = this.$router.resolve({
        path: '/entityDetail',
        query: {
          entityType: this.entityType,
          entityName: this.entityValue
        }
      })
      window.open(href, '_blank')
    },
    handleScoreData () {
      this.score = computeScore(this.performanceData, this.$store.getters.getScoreBase)
    }
  },
  /**
   * 页面销毁前，更新历史中已保存的状态
   * 之所以会在下钻时、销毁前保存状态，是因为panel第一次下钻时，beforeUnmount获取不到下钻前参数
   */
  beforeUnmount () {
    const query = this.$_.cloneDeep(this.$route.query)
    const routerObj = this.$store.getters.getRouterHistoryList.find(item => item.t === query.t)
    // const routerObj = window.localRouterHistoryList.find(item => item.t === query.t)
    if (routerObj !== undefined) {
      if (Object.getOwnPropertyNames(query).length >= Object.getOwnPropertyNames(routerObj.query).length) {
        routerObj.query = query
      }
    }

    this.emitter.off('reloadChartList')
    this.$store = null
    this.emitter = null
  }
}
</script>
