<template>
  <svg width="100%" height="100%" class="canvas" v-el:canvas
    :class="{highlighting: highlighting}"
  >
    <linearGradient id="outflow-gradient" x1="0" x2="0" y1="0" y2="1">
      <stop offset="0%" stop-color="#ec5540" stop-opacity="0.8"/>
      <stop offset="90%" stop-color="#ec5540" stop-opacity="0.8"/>
      <stop offset="100%" stop-color="#ec5540" stop-opacity="0"/>
    </linearGradient>

    <linearGradient id="outflow-gradient-hover" x1="0" x2="0" y1="0" y2="1">
      <stop offset="0%" stop-color="#ec5540" stop-opacity="1"/>
      <stop offset="90%" stop-color="#ec5540" stop-opacity="1"/>
      <stop offset="100%" stop-color="#ec5540" stop-opacity="0"/>
    </linearGradient>

    <linearGradient id="outflow-gradient-blur" x1="0" x2="0" y1="0" y2="1">
      <stop offset="0%" stop-color="#ec5540" stop-opacity="0.25"/>
      <stop offset="90%" stop-color="#ec5540" stop-opacity="0.25"/>
      <stop offset="100%" stop-color="#ec5540" stop-opacity="0"/>
    </linearGradient>

    <linearGradient id="hide-gradient">
      <stop offset="0%" stop-color="white"></stop>
      <stop offset="10%" stop-color="black"></stop>
      <stop offset="90%" stop-color="black"></stop>
      <stop offset="100%" stop-color="white"></stop>
    </linearGradient>
    <mask id="hide-mask" maskContentUnits="objectBoundingBox">
      <rect x="0" y="0" width="1" height="1" fill="url(#hide-gradient)" class=""></rect>
    </mask>

    <!-- flow -->
    <path
      v-for="path in filterPaths"
      v-if="path.render"
      class="connector"
      :class="{
        hidden: path.hidden && !highlighting,
        highlighting: path.data.highlight
      }"
      :d="getPathD(path)"
      @mouseenter="showTooltip(path, 'flow')"
      @mouseleave="hideTooltip"
      @click="highlight(path)">
    </path>
    <!-- outflow -->
    <path
      v-for="path in outflows"
      class="outflow"
      :class="{
        highlighting: path.data.highlight
      }"
      v-if="path.data.sectionIndex < maxIndex - 1"
      :d="getOutflowPathD(path)"
      @click="handleClickOutflow(path)"
      @mouseenter="showTooltip(path, 'outflow')"
      @mouseleave="hideTooltip">
    </path>
  </svg>
  <!-- tooltip -->
  <tooltip
    :class="{'tooltip-outflow': tooltip.type === 'outflow'}"
    v-if="tooltip.visible"
    :visible="tooltip.visible"
    @mouseleave="hideTooltip"
    :header="tooltip.header">
    <div>
      <template v-if="tooltip.type === 'flow'">
        <span v-if="!highlighting">{{ tooltip.data.value | fixedValue }}占总流量 {{ (tooltip.data.value / tooltip.data.total) | fixedPercent }}%</span>
        <span v-if="highlighting && tooltip.highlight">
          {{ tooltip.data.value | fixedValue }} / {{ tooltip.data.baseValue | fixedValue }} 会话数
        </span>
        <span v-if="highlighting && !tooltip.highlight && tooltip.highlightBase">
          {{ tooltip.data.highlightValue | fixedValue }} / {{ tooltip.data.value | fixedValue }} 会话数
        </span>
        <span v-if="highlighting && !tooltip.highlight && !tooltip.highlightBase">
          0 / {{ tooltip.data.value | fixedValue }} 会话数
        </span>
      </template>
      <template v-if="tooltip.type === 'outflow'">
        <template v-if="!highlighting">
          <div>{{ tooltip.data.outflow | fixedValue }} 流失</div>
          <div>占总流量 {{ (tooltip.data.outflow / tooltip.data.value) | fixedPercent }}%</div>
        </template>
        <template v-if="highlighting && tooltip.highlight">
          {{ tooltip.data.outflow | fixedValue }} / {{ tooltip.data.baseOutflow | fixedValue }} 流失次数
        </template>
        <template v-if="highlighting && !tooltip.highlight && tooltip.highlightBase">
          {{ tooltip.data.highlightOutflow | fixedValue }} / {{ tooltip.data.outflow | fixedValue }} 流失次数
        </template>
        <template v-if="highlighting && !tooltip.highlight && !tooltip.highlightBase">
          0 / {{ tooltip.data.outflow | fixedValue }} 流失次数
        </template>
      </template>
    </div>
  </tooltip>
</template>

<style scoped>
  .canvas {
    position: absolute;
    left: 0;
    top: 0;
  }
  .connector {
    fill: #d1dfe0;
    stroke: #d1dfe0;
    fill-opacity: 0.8;
    stroke-opacity: 1;
    stroke-width: 1;

    &:hover {
      fill-opacity: 1;
      cursor: pointer;
    }
    &.highlighting {
      fill: #88a4a4;
      stroke: #88a4a4;
      fill-opacity: 1;
    }
    &.hidden {
      pointer-events: none;
      mask: url(#hide-mask);
    }
  }
  .outflow {
    fill: url(#outflow-gradient);

    &:hover {
      cursor: pointer;
      fill: url(#outflow-gradient-hover);
    }
  }
  .canvas.highlighting {
    .connector:not(.highlighting) {
      fill-opacity: 0.25;
      stroke-opacity: 0.5;

      &:hover {
        fill-opacity: 1;
        stroke-opacity: 1;
      }
    }
    .outflow:not(.highlighting) {
      fill: url(#outflow-gradient-blur);

      &:hover {
        cursor: pointer;
        fill: url(#outflow-gradient-hover);
      }
    }
  }
</style>

<script type="text/ecmascript-6">
  // import Connector from './connector.vue';
  import Tooltip from './tooltip.vue';
  import { fixedValue, fixedPercent } from 'src/util';

  export default {
    props: ['paths', 'outflows'],

    filters: {
      fixedValue,
      fixedPercent
    },

    data() {
      return {
        maxIndex: 0,
        tooltip: {
          type: 'flow',
          data: {},
          visible: false,
          header: '',
          highlight: false
        },
        highlighting: false
      };
    },

    components: {
      // Connector,
      // Outflow,
      Tooltip
    },

    events: {
      'interactive-change'(val) {
        this.maxIndex = val;
      },
      'blur-path'() {
        this.highlighting = true;
      },

      'reset-path'() {
        this.highlighting = false;
      }
    },

    computed: {
      filterPaths() {
        if (!Array.isArray(this.paths)) return [];

        const cacheToPath = [];
        const cacheFirstFromPath = [];

        return this.paths.map(item => {
          const toPath = item.data.sectionIndex + ':' + item.data.to;

          if (item.data.highlight) {
            item.render = this.maxIndex > item.data.sectionIndex + 1;
            return item;
          }

          // 下游保留最大一根
          if (cacheToPath.indexOf(toPath) < 0) {
            cacheToPath.push(toPath);
            // 维度 Section 的每一个 Block 保留最大一根，第一个 Block 除外
          } else if (item.data.firstSection) {
            const firstFromPath = item.data.from;

            if (cacheFirstFromPath.indexOf(firstFromPath) < 0) {
              cacheFirstFromPath.push(firstFromPath);
            } else if (!item.data.firstBlock) {
              item.hidden = true;
            }
          } else {
            item.hidden = true;
          }

          item.render = this.maxIndex > item.data.sectionIndex + 1;
          return item;
        });
      }
    },

    methods: {
      showTooltip(path, type) {
        this.tooltip.type = type;
        this.tooltip.data = path.data;
        this.tooltip.visible = true;
        this.tooltip.highlight = path.data.highlight;
        this.tooltip.highlightBase = path.highlightBase;
        this.tooltip.header = type === 'flow'
          ? `[${path.data.from}到${path.data.to}]`
          : '';
      },
      hideTooltip() {
        this.tooltip.visible = false;
      },
      highlight(flow) {
        const data = flow.data;
        if (data.highlight) {
          this.$dispatch('reset');
        } else {
          this.$dispatch('select', {
            fromIndex: data.sectionIndex,
            toIndex: data.sectionIndex + 1,
            from: data.from,
            to: data.to,
            type: 'connector'
          });
        }
      },
      getPathD(data) {
        const x1 = data.x1;
        const y1 = data.y1;
        const x2 = data.x2;
        const y2 = data.y2;

        const START_WIDTH = 16;
        const BORDER_WIDTH = data.width;
        const PART = Math.round((x2 - x1) / 2);

        if (Math.abs(y1 - y2) <= 1) {
          return `M ${x1} ${y1} L ${x2},${y1} ${x2},${y1 + BORDER_WIDTH} ${x1}, ${y1 + BORDER_WIDTH}`;
        }

        return `M ${x1} ${y1} L ${x1 + START_WIDTH} ${y1} C ${x1 + PART} ${y1}, ${x1 + PART} ${y2}, ${x2 - START_WIDTH} ${y2} L ${x2} ${y2}, ${x2} ${y2 + BORDER_WIDTH}, ${x2 - START_WIDTH} ${y2 + BORDER_WIDTH} C ${x1 + PART} ${y2 + BORDER_WIDTH}, ${x1 + PART} ${y1 + BORDER_WIDTH}, ${x1 + START_WIDTH} ${y1 + BORDER_WIDTH} L ${x1} ${y1 + BORDER_WIDTH} Z`;
      },

      getStartLinePathD(data) {
        const x1 = data.x1;
        const y1 = data.y1;
        const START_WIDTH = 10;
        const BORDER_WIDTH = data.width;

        return `M ${x1} ${y1 + BORDER_WIDTH / 2} L ${x1 + START_WIDTH} ${y1 + BORDER_WIDTH / 2}`;
      },

      getEndLinePathD(data) {
        const x2 = data.x2;
        const y2 = data.y2;
        const START_WIDTH = 10;
        const BORDER_WIDTH = data.width;

        return `M ${x2 - START_WIDTH} ${y2 + BORDER_WIDTH / 2} L ${x2} ${y2 + BORDER_WIDTH / 2}`;
      },
      getOutflowPathD(data) {
        const x1 = data.x1;
        const y1 = data.y1;
        const LENGTHEN_Y = 10;
        const BORDER_WIDTH = data.width;
        const MAX_WIDTH = 35;
        const START_WDITH = BORDER_WIDTH <= MAX_WIDTH ? 5 : 10;

        if (data.data.highlight) {
          this.fill = 'url(#outflow-gradient-hover)';
          this.false = true;
        }

        return `M ${x1} ${y1} A ${START_WDITH / 2} ${START_WDITH / 2}, 0, 1, 1, ${x1} ${y1 + START_WDITH * 2} L ${x1 + START_WDITH} ${y1 + START_WDITH}, ${x1 + START_WDITH} ${y1 + BORDER_WIDTH + LENGTHEN_Y}, ${x1} ${y1 + BORDER_WIDTH + LENGTHEN_Y}`;
      },
      handleClickOutflow(outflow) {
        const data = outflow.data;

        if (data.highlight) {
          this.$dispatch('reset');
        } else {
          this.$dispatch('select', {
            from: data.path,
            fromIndex: data.sectionIndex,
            type: 'outflow'
          });
        }
      }
    },
    ready() {
    }
  };
</script>
