import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { select } from 'd3-selection';
import { tree, stratify } from 'd3-hierarchy';

function diagonal(d) {
    const offset = 50;
    return (
        'M' +
        d.y +
        ',' +
        d.x +
        'C' +
        (d.parent.y + offset) +
        ',' +
        d.x +
        ' ' +
        (d.parent.y + offset) +
        ',' +
        d.parent.x +
        ' ' +
        d.parent.y +
        ',' +
        d.parent.x
    );
}

const nodeRadius = 8;
const verticalSpaceBetweenNodes = 70;
const NARROW_HORIZONTAL_SPACES = 47;
const WIDE_HORIZONTAL_SPACES = 65;

const stratifyFn = stratify()
    .id(d => d.id)
    .parentId(d => d.parent);

class Tree extends Component {
    // state = {
    // 	startingCoordinates: null,
    // 	isDown: false
    // }

    static propTypes = {
        name: PropTypes.string,
        width: PropTypes.number,
        allowScaleWidth: PropTypes.bool,
        nodes: PropTypes.arrayOf(
            PropTypes.shape({
                id: PropTypes.string,
                name: PropTypes.string,
                parent: PropTypes.string
            })
        ),
        selectedNodeId: PropTypes.string,
        onNodeClick: PropTypes.func,
        onRenderedBeyondWidth: PropTypes.func
    };

    static defaultProps = {
        width: 500,
        allowScaleWidth: true,
        name: 'default-name'
    };

    render() {
        let { width, name, scrollable = false } = this.props;
        return (
            <div
                className={`tree-view ${name}-container ${
                    scrollable ? 'scrollable' : ''
                }`}>
                <svg width={width} className={name} />
            </div>
        );
    }

    componentDidMount() {
        this.renderTree();
    }

    // handleMouseMove(e) {
    // 	if (!this.state.isDown) {
    // 		return;
    // 	}
    // 	const container = select(`.tree-view.${this.props.name}-container`);
    // 	let coordinates = this.getCoordinates(e);
    // 	container.property('scrollLeft' , container.property('scrollLeft') + coordinates.x - this.state.startingCoordinates.x);
    // 	container.property('scrollTop' , container.property('scrollTop') + coordinates.y - this.state.startingCoordinates.y);
    // }

    // handleMouseDown(e) {
    // 	let startingCoordinates = this.getCoordinates(e);
    // 	this.setState({
    // 		startingCoordinates,
    // 		isDown: true
    // 	});
    // }

    // handleMouseUp() {
    // 	this.setState({
    // 		startingCorrdinates: null,
    // 		isDown: false
    // 	});
    // }

    // getCoordinates(e) {
    // 	var bounds = e.target.getBoundingClientRect();
    // 	var x = e.clientX - bounds.left;
    // 	var y = e.clientY - bounds.top;
    // 	return {x, y};
    // }

    componentDidUpdate(prevProps) {
        if (
            this.props.nodes.length !== prevProps.nodes.length ||
            this.props.selectedNodeId !== prevProps.selectedNodeId
        ) {
            this.renderTree();
        }
    }

    renderTree() {
        let {
            width,
            nodes,
            name,
            allowScaleWidth,
            selectedNodeId,
            onRenderedBeyondWidth,
            toWiden
        } = this.props;
        if (nodes.length > 0) {
            let horizontalSpaceBetweenLeaves = toWiden
                ? WIDE_HORIZONTAL_SPACES
                : NARROW_HORIZONTAL_SPACES;
            const treeFn = tree().nodeSize([
                horizontalSpaceBetweenLeaves,
                verticalSpaceBetweenNodes
            ]); //.size([width - 50, height - 50])
            let root = stratifyFn(nodes).sort((a, b) =>
                a.data.name.localeCompare(b.data.name)
            );
            let svgHeight =
                verticalSpaceBetweenNodes * root.height + nodeRadius * 6;

            treeFn(root);

            let nodesXValue = root.descendants().map(node => node.x);
            let maxX = Math.max(...nodesXValue);
            let minX = Math.min(...nodesXValue);

            let svgTempWidth =
                (maxX - minX) / 30 * horizontalSpaceBetweenLeaves;
            let svgWidth = svgTempWidth < width ? width - 5 : svgTempWidth;
            const svgEL = select(`svg.${name}`);
            const container = select(`.tree-view.${name}-container`);
            svgEL.html('');
            svgEL.attr('height', svgHeight);
            let canvasWidth = width;
            if (svgTempWidth > width) {
                if (allowScaleWidth) {
                    canvasWidth = svgTempWidth;
                }
                // we seems to have a margin of 25px that we can still see with text
                if (
                    svgTempWidth - 25 > width &&
                    onRenderedBeyondWidth !== undefined
                ) {
                    onRenderedBeyondWidth();
                }
            }
            svgEL.attr('width', canvasWidth);
            let rootGroup = svgEL
                .append('g')
                .attr(
                    'transform',
                    `translate(${svgWidth / 2 + nodeRadius},${nodeRadius *
                        4}) rotate(90)`
                );

            // handle link
            rootGroup
                .selectAll('.link')
                .data(root.descendants().slice(1))
                .enter()
                .append('path')
                .attr('class', 'link')
                .attr('d', diagonal);

            let node = rootGroup
                .selectAll('.node')
                .data(root.descendants())
                .enter()
                .append('g')
                .attr(
                    'class',
                    node =>
                        `node ${node.children ? ' has-children' : ' leaf'} ${
                            node.id === selectedNodeId ? 'selectedNode' : ''
                        } ${this.props.onNodeClick ? 'clickable' : ''}`
                )
                .attr(
                    'transform',
                    node => 'translate(' + node.y + ',' + node.x + ')'
                )
                .on('click', node => this.onNodeClick(node));

            node
                .append('circle')
                .attr('r', nodeRadius)
                .attr('class', 'outer-circle');
            node
                .append('circle')
                .attr('r', nodeRadius - 3)
                .attr('class', 'inner-circle');

            node
                .append('text')
                .attr('y', nodeRadius / 4 + 1)
                .attr('x', -nodeRadius * 1.8)
                .text(node => node.data.name)
                .attr('transform', 'rotate(-90)');

            let selectedNode = selectedNodeId
                ? root.descendants().find(node => node.id === selectedNodeId)
                : null;
            if (selectedNode) {
                container.property(
                    'scrollLeft',
                    svgWidth / 4 +
                        (svgWidth / 4 - 100) -
                        selectedNode.x / 30 * horizontalSpaceBetweenLeaves
                );
                container.property(
                    'scrollTop',
                    selectedNode.y / 100 * verticalSpaceBetweenNodes
                );
            } else {
                container.property(
                    'scrollLeft',
                    svgWidth / 4 + (svgWidth / 4 - 100)
                );
            }
        }
    }

    onNodeClick(node) {
        if (this.props.onNodeClick) {
            this.props.onNodeClick(node.data);
        }
    }
}

export default Tree;
