/**
 * 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.
 */


import React, { PureComponent } from 'react';
import { Tag, List, Card, Row, Col, Badge, Button } from 'antd';
import * as d3 from 'd3';
import moment from 'moment';
import { formatDuration } from '../../utils/time';
import DescriptionList from "../DescriptionList";
import styles from './index.less';

const { Description } = DescriptionList;

const height = 36;
const margin = 10;
const offX = 15;
const offY = 6;
const timeFormat = 'YYYY-MM-DD HH:mm:ss.SSS';
class TraceStack extends PureComponent {
  state = {
    nodes: [],
    idMap: {},
    colorMap: {},
    bap: [],
    span: {},
    key: 'tags',
  }

  componentWillMount() {
    const { spans } = this.props;
    const { colorMap } = this.state;
    const serviceList = Array.from(new Set(spans.map(i => i.serviceCode)));
    const sequentialScale = d3.scaleSequential()
    .domain([0, serviceList.length])
    .interpolator(d3.interpolateCool);
    spans.forEach((span) => {
      if (!colorMap[span.serviceCode]) {
        colorMap[span.serviceCode] = sequentialScale(serviceList.indexOf(span.serviceCode))
      }
      this.buildNode(span);
    });
    const { nodes } = this.state;
    const minStartTimeNode = nodes.reduce((acc, n) => (acc.startTime > n.startTime ? n : acc));
    this.state.nodes = nodes.map(n =>
      ({ ...n, startOffset: n.startTime - minStartTimeNode.startTime }));
  }

  componentDidMount() {
    
    this.state.width = this.axis.parentNode.clientWidth - 50;
    this.drawAxis();
    this.displayData();
    window.addEventListener('resize', this.resize);
  }

  onTabChange = (key, type) => {
    this.setState({ [type]: key });
  }

  buildNode = (span) => {
    const { nodes, idMap } = this.state;
    const node = {};
    node.serviceCode = span.serviceCode;
    node.startTime = span.startTime;
    node.endTime = span.endTime;
    node.duration = span.endTime - span.startTime;
    node.content = span.endpointName;
    node.spanSegId = this.id(span.segmentId, span.spanId);
    node.parentSpanSegId = this.findParent(span);
    node.refs = span.refs;
    node.type = span.type;
    node.peer = span.peer;
    node.component = span.component;
    node.isError = span.isError;
    node.layer = span.layer;
    node.tags = span.tags;
    node.logs = span.logs;
    nodes.push(node);
    idMap[node.spanSegId] = nodes.length - 1;
  }

  id = (...seg) => seg.join();

  findParent = (span) => {
    const { spans } = this.props;
    if (span.refs) {
      const ref = span.refs.find(_ => spans.findIndex(s =>
        this.id(_.parentSegmentId, _.parentSpanId) === this.id(s.segmentId, s.spanId)) > -1);
      if (ref) {
        return this.id(ref.parentSegmentId, ref.parentSpanId);
      }
    }
    const result = this.id(span.segmentId, span.parentSpanId);
    if (spans.findIndex(s => result === this.id(s.segmentId, s.spanId)) > -1) {
      return result;
    }
    return null;
  }

  drawAxis = () => {
    const { width } = this.state;
    const { nodes, bap } = this.state;
    const dataSet = nodes.map(node => node.startOffset + node.duration);
    const bits = d3.max(dataSet).toString().length;
    const percentScale = Math.ceil(d3.max(dataSet) / (10 ** (bits - 2)));
    const axisHeight = 20;

    const svg = d3.select(this.axis).append('svg')
      .attr('width', width)
      .attr('height', axisHeight)
      .attr('style', 'overflow: visible');

    const xScale = d3.scaleLinear()
      .domain([0, d3.max(dataSet)])
      .range([0, width]);

    const axis = d3.axisTop(xScale).ticks(4).tickSize([(height * nodes.length) + 40])
      .tickFormat(formatDuration);

    svg.append('g')
      .attr('class', styles.axis)
      .attr('transform', `translate(0, ${axisHeight})`)
      .call(axis);

    bap.push(bits);
    bap.push(percentScale);
    return bap;
  }

  displayData = () => {
    const { nodes, bap, width, colorMap } = this.state;
    const svgContainer = d3.select(this.duration).append('svg').attr('height', height * nodes.length).attr('style', 'overflow: visible');
    const positionMap = {};
    nodes.forEach((node, index) => {
      const { startOffset: startTime, duration, content,
        serviceCode, spanSegId, parentSpanSegId } = node;

      const rectWith = ((duration * width) / (bap[1] * (10 ** (bap[0] - 4)))) / 100;
      const beginX = ((startTime * width) / (bap[1] * (10 ** (bap[0] - 4)))) / 100;
      const bar = svgContainer.append('g').attr('transform', (d, i) => `translate(0,${i * height})`);

      const beginY = index * height;
      positionMap[spanSegId] = { x: beginX, y: beginY };
      const rectHeight = height - margin;
      const position = { width, top: beginY, left: beginX };
      const container = bar.append('rect').attr('spanSegId', spanSegId).attr('x', -5).attr('y', beginY - 5)
        .attr('width', width + 10)
        .attr('height', rectHeight + 10)
        .attr('class', styles.backgroudHide)
        .on('mouseover', () => { this.selectTimeline(container, true); })
        .on('mouseout', () => { this.selectTimeline(container, false); })
        .on('click', () => { this.showSpanModal(node, position, container); });

      bar.append('rect').attr('x', beginX).attr('y', beginY).attr('width', rectWith + 0.1)
        .attr('height', rectHeight)
        .on('mouseover', () => { this.selectTimeline(container, true); })
        .on('mouseout', () => { this.selectTimeline(container, false); })
        .on('click', () => { this.showSpanModal(node, position, container); })
        .style('fill', colorMap[serviceCode]);

      bar.append('text')
        .attr('x', () => {
          if ((width - beginX) < (content.length * 5.2)) {
            return beginX - content.length * 5.2 - 45
          }
          return beginX + 8;
        })
        .attr('y', (index * height) + (height / 2) - 2)
        .attr('class', styles.rectText)
        .on('mouseover', () => { this.selectTimeline(container, true); })
        .on('mouseout', () => { this.selectTimeline(container, false); })
        .on('click', () => { this.showSpanModal(node, position, container); })
        .text(`${content} ${formatDuration(duration)}`);
      if (node.isError) {
        bar.append('svg:image')
          .attr('xlink:href', 'img/icon/error.png')
          .attr('x', width + (rectHeight / 2))
          .attr('y', beginY)
          .attr('width', rectHeight)
          .attr('height', rectHeight);
      }
      if (index > 0 && positionMap[parentSpanSegId]) {
        const parentX = positionMap[parentSpanSegId].x;
        const parentY = positionMap[parentSpanSegId].y;

        const defs = svgContainer.append('defs');
        const arrowMarker = defs.append('marker')
          .attr('id', 'arrow')
          .attr('markerUnits', 'strokeWidth')
          .attr('markerWidth', 5)
          .attr('markerHeight', 5)
          .attr('viewBox', '-5 -5 10 10')
          .attr('refX', 0)
          .attr('refY', 0)
          .attr('orient', 'auto');
        arrowMarker.append('path')
          .attr('d', 'M 0,0 m -5,-5 L 5,0 L -5,5 Z')
          .attr('fill', '#8543e0').attr('opacity', 0.8);

        const parentLeftBottomX = parentX;
        const parentLeftBottomY = (Number(parentY) + Number(height)) - Number(margin);
        const selfMiddleX = beginX;
        const selfMiddleY = beginY + ((height - margin) / 2);
        if ((beginX - parentX) < 10) {
          svgContainer.append('line').attr('x1', parentLeftBottomX - offX).attr('y1', parentLeftBottomY - offY).attr('class', styles.connlines)
            .on('mouseover', () => { this.selectTimeline(container, true); })
            .on('mouseout', () => { this.selectTimeline(container, false); })
            .on('click', () => { this.showSpanModal(node, position, container); })
            .attr('x2', parentLeftBottomX)
            .attr('y2', parentLeftBottomY - offY);

          svgContainer.append('line').attr('x1', parentLeftBottomX - offX).attr('y1', parentLeftBottomY - offY).attr('class', styles.connlines)
            .on('mouseover', () => { this.selectTimeline(container, true); })
            .on('mouseout', () => { this.selectTimeline(container, false); })
            .on('click', () => { this.showSpanModal(node, position, container); })
            .attr('x2', parentLeftBottomX - offX)
            .attr('y2', selfMiddleY);

          svgContainer.append('line').attr('x1', parentLeftBottomX - offX).attr('y1', selfMiddleY).attr('class', styles.connlines)
            .on('mouseover', () => { this.selectTimeline(container, true); })
            .on('mouseout', () => { this.selectTimeline(container, false); })
            .on('click', () => { this.showSpanModal(node, position, container); })
            .attr('x2', selfMiddleX - 5)
            .attr('y2', selfMiddleY)
            .attr('marker-end', 'url(#arrow)');
        } else {
          svgContainer.append('line').attr('x1', parentLeftBottomX).attr('y1', parentLeftBottomY).attr('class', styles.connlines)
            .on('mouseover', () => { this.selectTimeline(container, true); })
            .on('mouseout', () => { this.selectTimeline(container, false); })
            .on('click', () => { this.showSpanModal(node, position, container); })
            .attr('x2', parentLeftBottomX)
            .attr('y2', selfMiddleY);

          svgContainer.append('line').attr('x1', parentLeftBottomX).attr('y1', selfMiddleY).attr('class', styles.connlines)
            .on('mouseover', () => { this.selectTimeline(container, true); })
            .on('mouseout', () => { this.selectTimeline(container, false); })
            .on('click', () => { this.showSpanModal(node, position, container); })
            .attr('x2', selfMiddleX - 5)
            .attr('y2', selfMiddleY)
            .attr('marker-end', 'url(#arrow)');
        }
      }
    });
  }

  selectTimeline = (container, isOver) => {
    if (this.state.container === container) {
      return;
    }
    container.attr('class', isOver ? styles.backgroud : styles.backgroudHide);
  }

  showSpanModal = (span, position, container) => {
    const { container: old } = this.state;
    if (old) {
      old.attr('class', styles.backgroudHide);
    }
    container.attr('class', styles.backgroudSelected);
    this.setState({
      ...this.state,
      span,
      key: 'tags',
      position,
      container,
    });
  }

  hideSpanModal = () => {
    const { container: old } = this.state;
    if (old) {
      old.attr('class', styles.backgroudHide);
    }
    this.setState({
      ...this.state,
      span: {},
      container: undefined,
    });
  }

  resize = () => {
    if (!this.axis) {
      return;
    }
    this.state.width = this.axis.parentNode.clientWidth - 50;
    if (!this.axis || this.state.width <= 0) {
      return;
    }
    this.axis.innerHTML = '';
    this.duration.innerHTML = '';
    this.drawAxis();
    this.displayData();
    this.setState({ ...this.state, span: {} });
  }

  renderTitle = (items) => {
    return (
      <Row type="flex" justify="start" gutter={15}>
        {
          items.map((_) => {
            return (
              <Col key={_.name}>
                <span>{_.name}</span>
                <Badge count={_.count} style={{ backgroundColor: '#1890FF', marginLeft: 5 }} />
              </Col>
            );
          })
        }
      </Row>
    );
  }

  render() {
    const { colorMap, span = {}, position = { width: 100, top: 0 } } = this.state;
    const legendButtons = Object.keys(colorMap).map(key =>
      (<Tag color={colorMap[key]} key={key}>{key}</Tag>));
    const tabList = [];
    const contentList = {};
    if (span.content) {
      tabList.push({
        key: 'tags',
        tab: 'Tags',
      });
      const base = [
        {
          title: 'span type',
          content: span.type,
        },
        {
          title: 'component',
          content: span.component,
        },
        {
          title: 'peer',
          content: span.peer,
        },
        {
          title: 'is error',
          content: `${span.isError}`,
        },
      ];
      const data = base.concat(span.tags.map(t => ({ title: t.key, content: t.value })));
      contentList.tags = (
        <DescriptionList layout="vertical">
          {data.map(_ =>
            <Description key={_.title} term={_.title}>{_.content}</Description>)}
        </DescriptionList>);
    }
    if (span.logs) {
      tabList.push({
        key: 'logs',
        tab: 'Logs',
      });
      contentList.logs = (
        <List
          itemLayout="horizontal"
          dataSource={span.logs}
          renderItem={log => (
            <List.Item>
              <List.Item.Meta
                size="small"
                title={moment(log.time).format('mm:ss.SSS')}
                description={
                  <DescriptionList layout="vertical" col={1}>
                    {log.data.map((_) => {
                      return (
                        <Description key={_.key} term={_.key}>
                          <pre className={styles.pre}>{_.value}</pre>
                        </Description>);
                    })}
                  </DescriptionList>
                }
              />
            </List.Item>
          )}
        />);
    }
    if (!span.parentSpanSegId && span.refs) {
      tabList.push({
        key: 'relatedTraces',
        tab: 'Related Trace',
      });
      contentList.relatedTraces = (
        <DescriptionList layout="vertical">
          {span.refs.map(_ => <Description key={_.type} term={_.type}>{_.traceId}</Description>)}
        </DescriptionList>);
    }
    const { top, left, width } = position;

    const toolTipStyle = { position: 'absolute', top: top + 86 };
    if (contentList.logs) {
      toolTipStyle.left = 0;
      toolTipStyle.width = width;
    } else {
      const right = width - left;
      if (left * 2 > width) {
        toolTipStyle.right = right;
        toolTipStyle.maxWidth = left;
      } else {
        toolTipStyle.left = left;
        toolTipStyle.maxWidth = right;
      }
    }
    return (
      <div className={styles.stack}>
        <div style={{ paddingBottom: 10 }}>
          { legendButtons }
        </div>
        <div className={styles.duration} ref={(el) => { this.duration = el; }} />
        <div ref={(el) => { this.axis = el; }} />
        {tabList.length > 0 ? (
          <Card
            type="inner"
            title={this.renderTitle([
              {
                name: 'Start Time',
                count: `${moment(span.startTime).format(timeFormat)}`,
              },
              {
                name: 'Duration',
                count: `${formatDuration(span.duration)}`,
              },
            ])}
            tabList={tabList}
            onTabChange={(key) => { this.onTabChange(key, 'key'); }}
            style={toolTipStyle}
            extra={<Button type="primary" shape="circle" icon="close" ghost onClick={this.hideSpanModal} />}
          >
            {contentList[this.state.key]}
          </Card>
        ) : null}
      </div>
    );
  }
}

export default TraceStack;
