import * as React from 'react';
import * as Styles from './styles';
import { isEqual } from 'lodash';
import { Transition } from 'react-transition-group';
import Step from './StepPoint';
import StepLine from './StepLine';
import { drop, map, zip, filter } from 'lodash';
import { StepProps } from "./index";
import {STEP_POINT_STATE, ThemeProps} from "./styles";
import {COLOR_PALETTE} from "../../constants/colors";


const circleRadius = 8;

export namespace StepperBar {
	export interface Props {
		steps: StepProps[];
		onStepClick: (step: StepProps) => void;
		currentStep?: number;
		unlockedIndex: number;
		clickable: boolean;
		isDone: boolean;
		doneIcon: any;
		theme?: ThemeProps;
	}
	export interface State {
		unlockedIndex: number;
		isLoaded: boolean;
		svg: {
			width: number;
			height: number;
			shiftSteps: number;
		}
	}
}

export default class StepperBar extends React.Component<StepperBar.Props, StepperBar.State> {
	private gEl: any;
	private containerNode: any;
	constructor(props: StepperBar.Props) {
		super(props);
		this.state = {
			unlockedIndex: props.unlockedIndex,
			isLoaded: false,
			svg: {
				height: 0,
				width: 0,
				shiftSteps: 0,
			}
		}
	}
	componentWillReceiveProps(nextProps) {
		if (this.props.unlockedIndex !== nextProps.unlockedIndex) {
			this.setState({ unlockedIndex: nextProps.unlockedIndex });
		}
		if (!isEqual(this.props.steps, nextProps.steps)) {
			this.updateBarPosition();
		}
	}

	componentDidUpdate(prevProps, prevState) {
		// wait for the bars and points to be added to the g element before getting it's width
		if (this.gEl && this.containerNode) {
			this.updateBarPosition();
		}
	}

	updateBarPosition = () => {
		if (this.gEl) {
			const { width } = this.gEl.getBoundingClientRect();
			if (this.state.svg.shiftSteps !== width) {
				this.setState(state => ({
					svg: {
						...state.svg,
						shiftSteps: width,
					}
				}));
			}
		}
	};

	handleContainerRef = node => {
		if (node) {
			const { height, width } = node.getBoundingClientRect();
			this.containerNode = node;
			this.setState(state => ({
				svg: {
					height,
					width,
					shiftSteps: state.svg.shiftSteps,
				}
			}))
		}
	};

	render() {
		return (
			<Styles.StepBarContainer innerRef={this.handleContainerRef}>
				<svg
					height={this.state.svg.height}
					width={this.state.svg.width}
				>
					<Styles.StepLine
						x1={0}
						x2={this.state.svg.width}
						state={STEP_POINT_STATE.INACTIVE}
						y1={this.state.svg.height / 2}
						y2={this.state.svg.height / 2}
						strokeWidth={'2'}
						theme={this.props.theme}
					/>
					<g ref={node => this.gEl = node} transform={`translate(${((this.state.svg.width / 2) - (this.state.svg.shiftSteps / 2) + ((5 + circleRadius) * 2))}, 0)`}>
						{map(this.props.steps, (step, idx) => {
							const { width } = this.state.svg;
							const barWidth = (width * (2/3)) / this.props.steps.length;
							return (
								<>
									<Step
										id={idx}
										onClick={this.props.onStepClick}
										clickable={this.props.clickable}
										key={`dot${idx}`}
										state={step.state}
										isActive={idx === this.props.currentStep}
										label={step.label}
										cx={barWidth * idx}
										cy={this.state.svg.height / 2}
										theme={this.props.theme}
									/>
									{idx !== this.props.steps.length - 1 && (
										<Transition in={idx < this.props.unlockedIndex}>
											{state => (
												<StepLine
													className={`${state}`}
													key={`bar${idx}`}
													color={this.props.theme && this.props.theme.stepColor ? this.props.theme.stepColor : COLOR_PALETTE.BLUE_DARK_1}
													x1={(barWidth * idx) + circleRadius}
													x2={(barWidth * (idx + 1)) - circleRadius}
													y={this.state.svg.height / 2}
												/>
											)}

										</Transition>
									)}
								</>
							)
						})}
					</g>
				</svg>
			</Styles.StepBarContainer>
		);
	}
}