<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at
  http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
  <div class="rk-trace-t flex-v">
    <div class="rk-trace-t-tool flex-h">
      <RkPage
        :currentSize="15"
        :currentPage="rocketTrace.traceForm.paging.pageNum"
        @changePage="page"
        :total="rocketTrace.traceTotal"
      />
      <select class="grey" @change="changeSort" :value="rocketTrace.traceForm.queryOrder">
        <option value="BY_START_TIME">{{ $t('startTime') }}</option>
        <option value="BY_DURATION">{{ $t('duration') }}</option>
      </select>
    </div>
    <div class="rk-trace-t-loading" v-show="loading">
      <svg class="icon loading">
        <use xlink:href="#spinner"></use>
      </svg>
    </div>
    <div class="rk-trace-t-wrapper scroll_hide">
      <table class="rk-trace-t">
        <tr class="rk-trace-tr cp" v-for="(i, index) in rocketTrace.traceList" @click="selectTrace(i)" :key="index">
          <td
            class="rk-trace-td"
            :class="{
              'rk-trace-success': !i.isError,
              'rk-trace-error': i.isError,
              selected: selectedKey == i.key,
            }"
          >
            <div
              class="ell mb-5"
              :class="{
                blue: !i.isError,
                red: i.isError,
              }"
            >
              <span class="b">{{ i.endpointNames[0] }}</span>
            </div>
            <div class="grey ell sm">
              <span class="rk-tag mr-10 sm">{{ i.duration }} ms</span>{{ parseInt(i.start) | dateformat }}
            </div>
          </td>
        </tr>
      </table>
    </div>
  </div>
</template>

<script lang="ts">
  import { Component, Vue, Watch } from 'vue-property-decorator';
  import { Action, Mutation, State } from 'vuex-class';
  import { State as traceState } from '@/store/modules/trace/index';
  @Component
  export default class TraceTable extends Vue {
    @State('rocketTrace') private rocketTrace!: traceState;
    @Mutation('rocketTrace/SET_TRACE_FORM_ITEM')
    private SET_TRACE_FORM_ITEM: any;
    @Mutation('rocketTrace/SET_CURRENT_TRACE') private SET_CURRENT_TRACE: any;
    @Mutation('rocketTrace/SET_DEFAULT_EMPTY_TRACE')
    private SET_DEFAULT_EMPTY_TRACE: any;
    @Action('rocketTrace/GET_TRACELIST') private GET_TRACELIST: any;
    @Action('rocketTrace/GET_TRACE_SPANS') private GET_TRACE_SPANS: any;
    private loading: boolean = false;
    private selectedKey: string = '';
    @Watch('rocketTrace.traceList')
    private onTraceListChange() {
      if (this.rocketTrace.traceList && this.rocketTrace.traceList.length > 0) {
        this.selectTrace(this.rocketTrace.traceList[0]);
      }
      if (this.rocketTrace.traceList && this.rocketTrace.traceList.length === 0) {
        this.SET_DEFAULT_EMPTY_TRACE();
      }
    }
    private selectTrace(i: any) {
      this.SET_CURRENT_TRACE(i);
      this.selectedKey = i.key;
      this.$eventBus.$emit('TRACE-TABLE-LOADING');
      this.$eventBus.$emit('TRACE-LIST-LOADING');
      if (i.traceIds.length) {
        this.GET_TRACE_SPANS({ traceId: i.traceIds[0] });
      }
    }
    private changeSort(e: any) {
      this.SET_TRACE_FORM_ITEM({
        type: 'queryOrder',
        data: e.target.options[e.target.selectedIndex].value,
      });
      this.SET_TRACE_FORM_ITEM({
        type: 'paging',
        data: { pageNum: 1, pageSize: 15, needTotal: true },
      });
      this.GET_TRACELIST();
    }
    private page(p: number) {
      this.loading = true;
      this.SET_TRACE_FORM_ITEM({
        type: 'paging',
        data: { pageNum: p, pageSize: 15, needTotal: true },
      });
      this.GET_TRACELIST().then(() => {
        this.loading = false;
      });
    }
    private created() {
      this.$eventBus.$on('SET_LOADING_TRUE', this, (cb: any) => {
        this.loading = true;
        if (cb) {
          cb();
        }
      });
      this.$eventBus.$on('SET_LOADING_FALSE', this, () => {
        this.loading = false;
      });
    }
  }
</script>
<style lang="scss">
  .rk-trace-t-tool {
    flex-shrink: 0;
    background-color: rgba(196, 200, 225, 0.2);
    justify-content: space-between;
    padding-right: 5px;
    select {
      background-color: rgba(0, 0, 0, 0);
      outline: 0;
      border-style: unset;
      margin: 0 10px;
    }
    padding-top: 1px;
    border-bottom: 1px solid #c1c5ca41;
    border-right: 1px solid #c1c5ca41;
    height: 35px;
  }
  .rk-trace-t-wrapper {
    overflow: auto;
    flex-grow: 1;
    border-right: 1px solid rgba(0, 0, 0, 0.1);
  }
  .rk-trace-t-loading {
    text-align: center;
    position: absolute;
    width: 100%;
    height: 70px;
    margin-top: 40px;
    line-height: 88px;
    overflow: hidden;
    .icon {
      width: 30px;
      height: 30px;
    }
  }
  .rk-trace-t {
    width: 100%;
    border-spacing: 0;
    table-layout: fixed;
    flex-grow: 1;
    position: relative;
  }
  .rk-trace-tr {
    &:hover {
      background-color: rgba(0, 0, 0, 0.04);
    }
  }
  .rk-trace-td {
    padding: 8px 10px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.07);
    &.selected {
      background-color: #ededed;
    }
  }
  .rk-trace-success {
    border-left: 4px solid rgba(46, 47, 51, 0.1);
  }
  .rk-trace-warning {
    border-left: 4px solid #fbb03b;
  }
  .rk-trace-error {
    border-left: 4px solid #e54c17;
  }
  .rk-tag {
    border-radius: 4px;
    padding-right: 5px;
    padding-left: 5px;
    background-color: #40454e;
    color: #eee;
  }
</style>