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
        ) {
            console.log('update');
            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;
