import React, { Component } from "react";
import _ from "lodash";
import moment from "moment";
import { FlexibleWidthXYPlot, LineSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, DiscreteColorLegend, Crosshair} from "react-vis";
import "../../../node_modules/react-vis/dist/style.css";



export function findClosestXValue(tagHistory, xval){
	const mapped = _.map(tagHistory, ({timestamp, value}) => {
		const timeInt = timestamp.getTime();
		return { dist: Math.abs(xval - timeInt), x: xval, y: value };
	});
	const sorted = _.orderBy(mapped, "dist", "asc");
	return(_.omit(sorted[0], "dist"));
}



/**
 * Map an array of objects to a graph-usable array of objects
 * 
 * @param  {Array} values - list of objects with timestame and value properties
 * 
 * @returns {Array} list of objects with x and y properties
 */
export const mapTimestampAndValuePropToXY = (values) => {
	return _.map(values, ({timestamp, value}) => {
		return {x: (new Date(timestamp)).getTime(), y: value};
	});
};


export class FlexibleGraph extends Component{
	constructor(props){
		super(props);
		// props.tagHistory
		// props.tags
		// props.tagDescriptions
		// props.units
		// props.round

		this.state = {
			crosshairValues: []
		};
	}

	tagsExist = () => {
		if (!this.props.tags){
			return false;
		}

		_.forEach(this.props.tags, (tag) =>{
			if (!tag || !tag.value){
				return false;
			}
		});

		_.forEach(this.props.tagHistory, (tag) => {
			if( !tag || !tag.value) {
				return false;
			}
		});
		return true;
	}
	
	renderLegendData = () =>{
		
		if (!this.tagsExist()){
			return _.map(this.props.tagDescriptions, (desc) => {
				return {title: desc};
			});
		} else {
			return _.map(this.props.tagDescriptions, (desc, key) => {
				return {title: `${desc}: ${_.round(this.props.tags[key].value, this.props.round[key])} ${this.props.units[key]}`};
			});
		}
	}

	renderCrossHairData = (values) => {
		const mappedValues = _.map(this.props.tagDescriptions, (desc, key) => {
			return {title: desc, value: _.round(values[key].y, 1) + ` ${this.props.units[key]}`};
		});
		console.log(mappedValues, this.props.tagDescriptions);
		return mappedValues;
	}

	renderTitleData = (values) => {
		return {title: "Time", value: moment(values[0].x).format("hh:mm A")};
	}

	/**
	 * Event handler for onMouseLeave.
	 * @private
	 */
	_onMouseLeave = ()  => {
		this.setState({crosshairValues: []});
	}

	/**
	 * Event handler for onNearestX.
	 * @param {Object} value Selected value.
	 * @param {index} index Index of the value in the data array.
	 * @private
	 */
	_onNearestX = (value) => {
		this.setState({
			crosshairValues: _.map(this.props.tagHistory, (tagHist) => {
				return findClosestXValue(tagHist, value.x);
			})
		});
	}
	
	render(){

		const lineSeries = _.map(this.props.tagHistory, (tag, key) => {
			if(key === 0){
				return <LineSeries key={key} data={mapTimestampAndValuePropToXY(tag)} onNearestX={this._onNearestX} />;
			} else {
				return <LineSeries key={key} data={mapTimestampAndValuePropToXY(tag)} />;
			}
			
		});

		if(!this.tagsExist()){
			return <span className="flexible-graph-notags"></span>;
		}

		return(
			<div className="flexible-graph">
				<FlexibleWidthXYPlot 
					height={300} 
					xType="time"
					onMouseLeave={this._onMouseLeave}
				>
					<VerticalGridLines />
					<HorizontalGridLines />
					<XAxis />
					<YAxis />
					{lineSeries}
					<Crosshair 
						values={this.state.crosshairValues} 
						titleFormat={this.renderTitleData} 
						itemsFormat = {this.renderCrossHairData}
					/>
				</FlexibleWidthXYPlot>
				<DiscreteColorLegend 
					items={this.renderLegendData()}
					orientation="horizontal"
				/>
			</div>
		);
	}
}