import React, { Component } from 'react';
import {
	BlinkDot,
	BreadBoard,
	Path,
	SVGImage,
	Wire
} from 'components';
import ReactDOM from 'react-dom';

import Arduino from './Arduino.react'
import Relay from './Relay.react'

import {
	getObjectById,
	getSlotPositionXYById,
	getComponentSlotPositionById,
	getSlotIdByName,
	getComponentDetailsById,
	getDistanceBetweenTwoPoints,
	removeAllComponentOptions,
	highlightComponentOptionById,
	isComponentAlreadyPlaced,
	generateWirePathData,
	isBlinkDotExists,
	isComponentExists
} from 'utils/ioty';

export default class SVGPanel extends Component {
	constructor (props) {
		super(props);

		this.mouseXY = {}
		this.selectedComponentOptionId = -1
		this.arduino = null
		this.arduinoLoaded = false
		this.relay = null
		this.relayLoaded = false,
		this.minDistanceOptions = []
		this.minDistancePositions = []

		this.mouseClicksCount = 0

		this.loadExistedCircuitDataOnBreadBoard = this.loadExistedCircuitDataOnBreadBoard.bind(this)
		this.loadComponent = this.loadComponent.bind(this)
		this.setMouseXY = this.setMouseXY.bind(this)
		this.loadDataUptoCurrentStep = this.loadDataUptoCurrentStep.bind(this)
		this.placeComponent = this.placeComponent.bind(this)
		this.drawConnectionWire = this.drawConnectionWire.bind(this)
		this.drawWire = this.drawWire.bind(this)
		this.clickHandler = this.clickHandler.bind(this)
		this.markOrBlinkSlot = this.markOrBlinkSlot.bind(this)
		this.adjustComponentPosition = this.adjustComponentPosition.bind(this)
		this.adjustClickPositionToSlotPosition = this.adjustClickPositionToSlotPosition.bind(this)
		this.adjustClickPositionToGivenSlotsPosition = this.adjustClickPositionToGivenSlotsPosition.bind(this)
		this.getAllSlotPositionsByComponent = this.getAllSlotPositionsByComponent.bind(this)
		this.findNearestPosition = this.findNearestPosition.bind(this)
		this.removeOtherSlotsOnVLabPanel = this.removeOtherSlotsOnVLabPanel.bind(this)
		this.displaySlots = this.displaySlots.bind(this)

		this.undoComponentSelection = this.undoComponentSelection.bind(this)

		this.state = {
			renderExistedCircuitData : [],
			renderNewCircuitData : [],
			renderConnectionWires : [],
			renderExistedCircuitComponents : [],
			renderBlinkDots : []
		}
	}

	//componentWillReceiveProps method will be called when local json is loaded 
	componentWillReceiveProps (nextProps) {
	 	this.loadExistedCircuitDataOnBreadBoard(nextProps)
	 	if (this.props.currentStep === nextProps.currentStep && this.props.currentStepSelectedOptions.componentId !== -1) {
	 		this.undoComponentSelection(this.props, nextProps)
	 		this.mouseClicksCount = 0
	 		this.minDistanceOptions = []
	 		this.minDistancePositions = []
	 	}
	 	if ( (this.props.currentStep !== nextProps.currentStep) && (JSON.stringify(this.props.userSelectedStepOptions) === JSON.stringify(nextProps.userSelectedStepOptions)) ) {
	 		this.loadDataUptoCurrentStep(nextProps, this.props)
	 	} else {
	 		let selectedComponentDetails, selectedComponentId
		 	if (nextProps.currentStepSelectedOptions !== '' && nextProps.currentStepSelectedOptions.componentId !== -1) {
		 		selectedComponentId = nextProps.currentStepSelectedOptions.componentId
		 		selectedComponentDetails= getComponentDetailsById(nextProps.newCircuitData, selectedComponentId)
		 		if (selectedComponentDetails === {}) {
		 			alert ('ERROR : No such component found!')
		 		} else {
		 			// console.log('loadComponent called in componentWillReceiveProps else');
		 			this.loadComponent(selectedComponentDetails, nextProps.currentStepSelectedOptions)
		 		}
		 	}
	 	}
	}

	undoComponentSelection (prevProps, nextProps) {
		let {renderBlinkDots, renderNewCircuitData, renderConnectionWires} = this.state
		renderNewCircuitData = renderNewCircuitData.slice()
		if ( nextProps.currentStepSelectedOptions.componentId === -1 ) {
 			let index, selectedComponentDetails
 			if ( prevProps.currentStepSelectedOptions.componentOptionId !== -1 && renderNewCircuitData.length > 0) {
 				selectedComponentDetails = getObjectById(prevProps.newCircuitData, 'componentId', prevProps.currentStepSelectedOptions.componentId)
 				if (selectedComponentDetails !== -1) {
 					index = isComponentExists(
 						selectedComponentDetails.componentMultimediaURL.startsWith('#') ? renderConnectionWires : renderNewCircuitData, 
 						prevProps.currentStepSelectedOptions.componentId, 
 						prevProps.currentStepSelectedOptions.stepId)
 				}
 			}
 			if (renderBlinkDots.length !== 0 || index !== undefined) {
 				if (index !== -1 && index !== undefined) {
 					selectedComponentDetails.componentMultimediaURL.startsWith('#') ? renderConnectionWires.splice(index,1) : renderNewCircuitData.splice(index, 1)
 				}
				this.setState({
					renderBlinkDots : [],
					renderNewCircuitData : renderNewCircuitData,
					renderConnectionWires : renderConnectionWires
				})
			}
 		} else {
 			let index, selectedComponentDetails
 			if (nextProps.currentStepSelectedOptions.componentOptionId === -1 && renderNewCircuitData.length > 0) {
 				selectedComponentDetails = getObjectById(prevProps.newCircuitData, 'componentId', prevProps.currentStepSelectedOptions.componentId)
 				if (selectedComponentDetails !== -1) {
 					index = isComponentExists(
 						selectedComponentDetails.componentMultimediaURL.startsWith('#') ? renderConnectionWires :  renderNewCircuitData, 
 						prevProps.currentStepSelectedOptions.componentId, 
 						nextProps.currentStepSelectedOptions.stepId)
 				}
 			}
 			if (renderBlinkDots.length !== 0 || index !== undefined) {
 				if (index !== -1 && index !== undefined) {
 					selectedComponentDetails.componentMultimediaURL.startsWith('#') ? renderConnectionWires.splice(index, 1) :  renderNewCircuitData.splice(index, 1)
 				}
				this.setState({
					renderBlinkDots : [],
					renderNewCircuitData : renderNewCircuitData,
					renderConnectionWires : renderConnectionWires
				})
			}
 		}
	}

	loadDataUptoCurrentStep (nextProps, prevProps) {
		let {currentStep, userSelectedStepOptions, steps} = nextProps

		for (let i=0;i<currentStep;i++) {
			let {stepId, componentId, componentOptionId} = userSelectedStepOptions[i]
			let currentStepDetails = getObjectById(steps, 'stepId', stepId)
			let selectedComponentDetails;
			if (currentStepDetails.stepType === 'TYPE_CIRCUIT') {
				let components = currentStepDetails.components
				selectedComponentDetails = getObjectById(components, 'componentId', componentId)
				if (selectedComponentDetails === -1) {
					return;
				}
				if (selectedComponentDetails.componentMultimediaURL.startsWith('#')) {
					//draw wire
					//drawWire(wireDetails, point1, point2)
					let {componentOptions} = selectedComponentDetails
					let selectedOptionDetails = getObjectById(componentOptions, 'optionId', componentOptionId)
					let point1, point2, wirePositions = [],slotIds = []
					slotIds = selectedOptionDetails.slots.map(function (slotObj, slotIndex) {
						return getSlotIdByName(slotObj.slot)
					})
					this.setState({
						renderConnectionWires : [],
						renderNewCircuitData : [],
						renderBlinkDots : []
					}, function () {
						this.drawWire(selectedComponentDetails, currentStep, userSelectedStepOptions, slotIds)
					}, this)
				} else {
					//place component
					//placeComponent(componentDetails, position)
					let {componentName, componentOptions, terminalPositions }	= selectedComponentDetails
					let selectedOptionDetails = getObjectById(componentOptions, 'optionId', componentOptionId)
					let componentPosition;
					if (selectedOptionDetails !== -1) {
						selectedOptionDetails.slots.map(function (slotObj, slotIndex) {
							let slotId;
							slotId = getSlotIdByName(slotObj.slot)
							if (selectedOptionDetails.slots[slotIndex].label === '+') {
								componentPosition = getSlotPositionXYById(slotId)
							}
						},this)
						componentPosition = this.adjustClickPositionToSlotPosition(componentPosition)
						componentPosition = this.adjustComponentPosition(componentPosition, terminalPositions)
						this.setState({
							renderNewCircuitData : [],
							renderConnectionWires : [],
							renderBlinkDots : []
						}, function () {
							this.placeComponent(selectedComponentDetails, componentPosition, currentStep, userSelectedStepOptions)
						}, this)
					}
				}
			}
		}
	}

	drawWire (wireDetails, currentStep, userSelectedStepOptions, slotIds) {
		let WireProps = {}
		let {componentId, componentName, componentMultimediaURL} = wireDetails
		let currentStepSelectedOptions = userSelectedStepOptions[currentStep-1]
		WireProps.stepId = currentStepSelectedOptions.stepId
		WireProps.componentId = componentId
		WireProps.componentName = componentName
		WireProps.color = componentMultimediaURL
		WireProps.path = generateWirePathData(slotIds, componentId).currentPath
		

		let renderConnectionWires = this.state.renderConnectionWires
		renderConnectionWires.push(
			<Wire key={renderConnectionWires.length} {...WireProps} />
		)
		this.setState({
			renderConnectionWires : renderConnectionWires,
			renderBlinkDots : []
		}, function () {
			// console.log('called removeOtherSlotsOnVLabPanel drawWire', userSelectedStepOptions);
			this.removeOtherSlotsOnVLabPanel(this.state.renderBlinkDots, userSelectedStepOptions[currentStep-1].componentOptionId, wireDetails)
		},this)
	}

	placeComponent (componentDetails, componentPosition, currentStep, userSelectedStepOptions) {
		let SVGImageProps = {}
		let {componentId, componentName, componentMultimediaURL} = componentDetails
		SVGImageProps.stepId = userSelectedStepOptions[currentStep - 1].stepId
		SVGImageProps.componentId = componentId
		SVGImageProps.componentName = componentName
		SVGImageProps.componentMultimediaURL = componentMultimediaURL
		SVGImageProps.translateX = componentPosition.x
		SVGImageProps.translateY = componentPosition.y
		SVGImageProps.setPushButtonState = this.props.IoTyActions.setPushButtonState

		let renderNewCircuitData = this.state.renderNewCircuitData
		renderNewCircuitData.push(
			<SVGImage {...SVGImageProps} key={renderNewCircuitData.length} />
		)
		this.setState({
			renderNewCircuitData : renderNewCircuitData,
			renderBlinkDots : []
		}, function () {
			let steps = this.props.steps
			for (let i=0;i<steps.length;i++) {
				// console.log('removeAllComponentOptions triggered');
				removeAllComponentOptions(steps[i].components)	
			}
			// highlightComponentOptionById(this.props.steps, currentStep, userSelectedStepOptions)
		},this)
	}

	clickHandler (e) {
		if (this.props.currentStepSelectedOptions.componentOptionId === -1) {
			var svg = document.getElementById('svgPanel');
			var pt = svg.createSVGPoint();
			pt.x = e.clientX;
			pt.y = e.clientY;
			let point = pt.matrixTransform(svg.getScreenCTM().inverse())
			this.setMouseXY(point)
		}
	}

	/*
		setMouseXY : sets the position of mouse when click event happen on any breadboard slot
		value to be set : {x : Rounded up to the next multiple of 10, y: Rounded up to the next multiple of 5}
	*/
	setMouseXY (point) {
		this.mouseClicksCount = this.mouseClicksCount + 1
		// this.mouseXY = {x : Math.ceil(point.x / 10) * 10, y : Math.ceil(point.y / 5) * 5}
		this.mouseXY = this.adjustClickPositionToSlotPosition(point)
		// console.log('this.mouseXY', this.mouseXY);
		let selectedComponentDetails, selectedComponentId = this.props.currentStepSelectedOptions.componentId
	 	if (selectedComponentId !== -1) {
	 		selectedComponentDetails= getComponentDetailsById(this.props.newCircuitData, selectedComponentId)
	 		if (selectedComponentDetails === {}) {
	 			alert ('ERROR : No such component found!')
	 			return
	 		}
	 		let componentResolution, componentPosition, SVGImageProps = {}
			let {componentId, componentName, componentMultimediaURL, componentOptions, terminalPositions} = selectedComponentDetails
			// componentResolution = this.getComponentWidthHeightByName(componentName)
			componentPosition = this.mouseXY
			componentPosition =  this.adjustClickPositionToGivenSlotsPosition(componentPosition, selectedComponentDetails)
			// console.log('got componentPosition', componentPosition);
			let optionId = componentPosition.optionId
			let selectedOptionDetails = getObjectById(componentOptions, 'optionId', optionId),
				selectedOptionSlots = null
			if (selectedOptionDetails !== -1) {
				selectedOptionSlots = selectedOptionDetails.slots
			}
			let positiveSlot = getObjectById(selectedOptionSlots, 'label', '+')
			// console.log('got positiveSlot', positiveSlot, selectedOptionDetails);
			let slotId = getSlotIdByName(positiveSlot.slot)
			if (slotId.startsWith('AR') || slotId.startsWith('relay')) {
				componentPosition = getComponentSlotPositionById('svgPanel', slotId)
			} else {
				componentPosition = getSlotPositionXYById(slotId)
			}
			componentPosition = this.adjustComponentPosition(componentPosition, terminalPositions)
			if (componentMultimediaURL.startsWith('#')) {
				// console.log('drawConnectionWire called in setMouseXY');
				this.drawConnectionWire(selectedComponentDetails, this.props.currentStepSelectedOptions, true)
				return
			}

			SVGImageProps.stepId = this.props.currentStepSelectedOptions.stepId
			SVGImageProps.componentId = componentId
			SVGImageProps.componentName = componentName
			SVGImageProps.translateX = componentPosition.x 
			SVGImageProps.translateY = componentPosition.y
			SVGImageProps.componentMultimediaURL = componentMultimediaURL
			SVGImageProps.setPushButtonState = this.props.IoTyActions.setPushButtonState


			let renderNewCircuitData = this.state.renderNewCircuitData
			let renderBlinkDots = this.state.renderBlinkDots
			let newCircuitComponent = <SVGImage {...SVGImageProps} key={renderNewCircuitData.length}/>
			/**
			*	PUT THIS BELOW STATEMENT IN A CONDITION
			**/
			if (!isComponentAlreadyPlaced(renderNewCircuitData, newCircuitComponent.props.componentId) && renderBlinkDots.length > 0) {
				renderNewCircuitData.push(
					newCircuitComponent
				)
				this.setState({
					renderNewCircuitData : renderNewCircuitData,
					renderBlinkDots : []
				}, function () {
					// console.log('called removeOtherSlotsOnVLabPanel setMouseXY');
					if (this.props.currentStepSelectedOptions.componentOptionId !== -1) {
						this.mouseClicksCount = 0
						this.minDistanceOptions = []
						this.minDistancePositions = []
					}
					this.removeOtherSlotsOnVLabPanel(this.state.renderBlinkDots, optionId, selectedComponentDetails)
				},this)
			}		
	 	}
	}

	/*
		loadExistedCircuitDataOnBreadBoard : uses existedCircuitData prop value and load all components on breadboard
	*/
	loadExistedCircuitDataOnBreadBoard (nextProps) {
		let existedCircuitData = nextProps.existedCircuitData,
			isNewComponent = false
		this.arduinoLoaded = nextProps.arduinoLoaded
		// console.log('existedCircuitData ', existedCircuitData);
		if (existedCircuitData !== undefined && existedCircuitData !== null) {
			for (let i=0;i<existedCircuitData.length;i++) {
				// console.log('loadComponent called in loadExistedCircuitDataOnBreadBoard');
				this.loadComponent(existedCircuitData[i], this.props.currentStepSelectedOptions, isNewComponent)
			}
		}
	}


	drawConnectionWire (wire, currentStepSelectedOptions, isNewComponent) {
		let {componentId, componentName, componentOptions, componentMultimediaURL, terminalPositions} = wire
		let WireProps = {}, slotIds= []
		if (componentOptions !== undefined && componentOptions !== null && (isNewComponent || componentOptions.length === 1)) {
			for (let i=0;i<componentOptions.length;i++) {
				let slots = componentOptions[i].slots;
				if (slots !== undefined && slots !== null) {
					for (let j=0;j<slots.length;j++) {
						let slotId = getSlotIdByName(slots[j].slot)
						// console.log('blinking called in drawConnectionWire');
						let renderBlinkDots = this.state.renderBlinkDots,
							index = isBlinkDotExists(renderBlinkDots, slotId+'__'+componentMultimediaURL)
						if (isNewComponent && (renderBlinkDots.length === 0 || index === -1 )) {
							// console.log('markOrBlinkSlot triggerd @drawConnectionWire');
							this.markOrBlinkSlot(isNewComponent, slotId, componentOptions[i].color)
						}
					}
				}
			}
		} else {
			alert ('Already existed component should have only one option')
		}
		let currentSelectedComponentDetails, optionId, currentSelectedOptionDetails
		if (isNewComponent) {
			currentSelectedComponentDetails = getObjectById(this.props.newCircuitData, 'componentId', currentStepSelectedOptions.componentId)
			// console.log('currentSelectedComponentDetails', currentSelectedComponentDetails);
			optionId = currentStepSelectedOptions.componentOptionId === -1 ? this.selectedComponentOptionId : currentStepSelectedOptions.componentOptionId
			currentSelectedOptionDetails = getObjectById(currentSelectedComponentDetails.componentOptions, 'optionId', optionId)
			// console.log('currentSelectedOptionDetails', currentSelectedOptionDetails);
			if (currentSelectedOptionDetails !== -1) {
				slotIds = currentSelectedOptionDetails.slots.map(function (slot) {
					return getSlotIdByName(slot.slot)
				})
			}
		} else {
			slotIds = componentOptions[0].slots.map(function (slot) {
				return getSlotIdByName(slot.slot)
			})
		}

		let renderConnectionWires = this.state.renderConnectionWires
		if (currentStepSelectedOptions.componentOptionId !== -1) {
			WireProps.stepId = currentStepSelectedOptions.stepId
			WireProps.componentId = componentId
			WireProps.componentName = componentName
			WireProps.color = componentMultimediaURL
			WireProps.path = generateWirePathData(slotIds, componentId).currentPath
			let WireComponent = <Wire key={renderConnectionWires.length} {...WireProps}/>
			// console.log('renderConnectionWires', renderConnectionWires);
			if (!isComponentAlreadyPlaced(renderConnectionWires, WireComponent.props.componentId) && this.state.renderBlinkDots.length > 0) {
				// console.log('New wire componnet');
				renderConnectionWires.push(
					WireComponent
				)
				this.setState({
					renderConnectionWires : renderConnectionWires,
					renderBlinkDots : []
				}, function () {
					if (currentStepSelectedOptions.componentOptionId !== -1 && isNewComponent) {
						// console.log('called removeOtherSlotsOnVLabPanel drawConnectionWire');
						this.mouseClicksCount = 0
						this.removeOtherSlotsOnVLabPanel(this.state.renderBlinkDots, optionId, wire)
					}
				},this)
			}
		}
	}

	/*
		loadComponent : takes component as input and loads that component on breadboard
	*/
	loadComponent (component, currentStepSelectedOptions, isNewComponent = true) {
		let componentResolution, componentPosition, SVGImageProps = {}
		let {componentId, componentName, componentOptions, componentMultimediaURL, terminalPositions} = component
		// componentResolution = this.getComponentWidthHeightByName(componentName)
		let renderExistedCircuitComponents = this.state.renderExistedCircuitComponents
		if (componentMultimediaURL === 'arduino') {
			// console.log('load arduino');
			this.arduino = <Arduino arduinoLoaded={this.props.IoTyActions.arduinoLoaded} />
			return
		} else if (componentMultimediaURL === 'relay') {
			this.relay = <Relay />
			return
		} else if (componentMultimediaURL.startsWith('#')) {
			// console.log('arduinoLoaded', this.props.arduinoLoaded);
			if (this.arduinoLoaded) {
				// console.log('drawConnectionWire called in loadComponent');
				this.drawConnectionWire(component, currentStepSelectedOptions, isNewComponent)
			}
			return
		} 
		// console.log('blinking slots goes here');
		if (componentOptions !== undefined && componentOptions !== null && (isNewComponent || componentOptions.length === 1)) {
			// console.log('before for loop');
			for (let i=0;i<componentOptions.length;i++) {
				let slots = componentOptions[i].slots;
				if (slots !== undefined && slots !== null) {
					for (let j=0;j<slots.length;j++) {
						let slotId = getSlotIdByName(slots[j].slot)
						if (slotId === -1) {
							alert ('Unrecognised slot given')
							return
						}
						if (slots[j].label == '+') {		//	PLACING COMPONENT ALWAYS BASED ON POSITIVE TERMINAL (+)
							componentPosition = getSlotPositionXYById(slotId)
						}
						// console.log('blinking called in loadComponent');
					}
				}
			}
			this.setState({
				renderBlinkDots : []
			}, function () {
				if (currentStepSelectedOptions.componentOptionId === -1) {
					for (let i=0;i<componentOptions.length;i++) {
						let slots = componentOptions[i].slots;
						if (slots !== undefined && slots !== null) {
							for (let j=0;j<slots.length;j++) {
								let slotId = getSlotIdByName(slots[j].slot)
								if (isNewComponent) {
									// console.log('markOrBlinkSlot triggerd @loadComponent');
									this.markOrBlinkSlot(isNewComponent, slotId, componentOptions[i].color)
								}
								// console.log('blinking called in loadComponent');
							}
						}
					}
				}
			}.bind(this))
		} else {
			alert ('Already existed component should have only one option')
		}

		componentPosition = this.adjustComponentPosition(componentPosition, terminalPositions)
		SVGImageProps.stepId = currentStepSelectedOptions.stepId
		SVGImageProps.componentId = componentId
		SVGImageProps.componentName = componentName
		/*SVGImageProps.width = componentResolution.width
		SVGImageProps.height = componentResolution.height*/
		SVGImageProps.translateX = componentPosition.x 
		SVGImageProps.translateY = componentPosition.y
		SVGImageProps.componentMultimediaURL = componentMultimediaURL
		SVGImageProps.setPushButtonState = this.props.IoTyActions.setPushButtonState

		let renderExistedCircuitData = this.state.renderExistedCircuitData
		let renderBlinkDots = this.state.renderBlinkDots
		let SVGImageComponent = <SVGImage {...SVGImageProps} key={renderExistedCircuitData.length}/>
		if (!isNewComponent && !isComponentAlreadyPlaced(renderExistedCircuitData, SVGImageComponent.props.componentId) && renderBlinkDots.length > 0){ 	//HAVE TO CHANGE THIS CONDITION APPROPRIATELY
			renderExistedCircuitData.push(
				SVGImageComponent
			)
			this.setState({
				renderExistedCircuitData : renderExistedCircuitData,
				renderBlinkDots : []
			}, function () {
				if (currentStepSelectedOptions.componentOptionId !== -1) {
					this.mouseClicksCount = 0
				}
			})
		}
	}

	/*
		adjustComponentPosition : takes 2 arguments and adjusts the component position based on current position and terminal(component connection point) positions
	*/
	adjustComponentPosition (currentPosition, terminalPositions) {
		let {x, y} = currentPosition,
			terminalPosition = terminalPositions[0]
		x -= terminalPosition.x
		y -= terminalPosition.y
		return {x, y}
	}

	/*
		markOrBlinkSlot : takes 3 arguments blink (boolean), slotId, slotColor and adds css to slot using given slot id
	*/
	markOrBlinkSlot (blink, slotId, slotColor) {
		let renderBlinkDots = this.state.renderBlinkDots,
			slotPosition = null
		if (slotId.startsWith('AR') || slotId.startsWith('relay')) {
			slotPosition = getComponentSlotPositionById('svgPanel', slotId)
		} else {
			slotPosition = getSlotPositionXYById(slotId)
		}
		let blinkDotProps = {
			key : slotId+'__'+slotColor,
			id : slotId+'__'+slotColor,
			radius : '3',
			cx : slotPosition.x,
			cy : slotPosition.y,
			color : slotColor,
			blink : blink
		}
		// console.log('renderBlinkDots', renderBlinkDots, slotId);
		let index = isBlinkDotExists(renderBlinkDots, slotId+'__'+slotColor)
		if (index === -1) {
			renderBlinkDots.push(
				<BlinkDot {...blinkDotProps} />
			)
		} else {
			let props = JSON.parse(JSON.stringify(renderBlinkDots[index].props))
			let key = JSON.parse(JSON.stringify(renderBlinkDots[index].key))
			Object.assign(
				props,
				{
					blink : true,
					key : key
				}
			)
			renderBlinkDots[index] = <BlinkDot {...props}/>
		}
		this.setState({
			renderBlinkDots : renderBlinkDots
		}, function () {
			// console.log('damn execution!');
		})
	}

	removeOtherSlotsOnVLabPanel (blinkDotList, optionId, selectedComponentDetails) {
		// console.log('called removeOtherSlotsOnVLabPanel', optionId);
		// let selectedComponentDetails = getObjectById(this.props.newCircuitData, 'componentId', this.props.currentStepSelectedOptions.componentId)
		let renderUpdatedBlinkDots = []
		if (selectedComponentDetails.componentMultimediaURL.startsWith('#') && optionId !== -1) {
			let selectedOptionDetails = getObjectById(selectedComponentDetails.componentOptions, 'optionId', optionId)
			let slots = selectedOptionDetails.slots
			for(let i=0;i<slots.length;i++) {
				let slotId = getSlotIdByName(slots[i].slot)
				let index = isBlinkDotExists(blinkDotList, slotId+'__'+selectedComponentDetails.componentMultimediaURL)
				if (index !== -1) {
					let props = JSON.parse(JSON.stringify(blinkDotList[index].props))
					let key = JSON.parse(JSON.stringify(blinkDotList[index].key))
					Object.assign(
						props,
						{
							blink : false,
							key : key
						}
					)
					renderUpdatedBlinkDots.push(
						<BlinkDot {...props}/>
					)
				}
			}
		}
		this.setState({
			renderBlinkDots : renderUpdatedBlinkDots
		}, function () {
			// console.log('updated renderBlinkDots');
		})
	}

	displaySlots (blinkDotList, optionId, selectedComponentDetails) {
		let renderUpdatedBlinkDots = []
		if (selectedComponentDetails.componentMultimediaURL.startsWith('#') && optionId !== -1) {
			// console.log('wire details got');
			let selectedOptionDetails = getObjectById(selectedComponentDetails.componentOptions, 'optionId', optionId)
			let slots = selectedOptionDetails.slots,
				slotPosition = null
			for(let i=0;i<slots.length;i++) {
				let slotId = getSlotIdByName(slots[i].slot)
				let index = isBlinkDotExists(blinkDotList, slotId+'__'+selectedComponentDetails.componentMultimediaURL),
					props = null
				if (index === -1) {
					// console.log('not exists --> optionId slotId', optionId, slotId);
					if (slotId.startsWith('AR') || slotId.startsWith('relay')) {
						slotPosition = getComponentSlotPositionById('svgPanel', slotId)
					} else {
						slotPosition = getSlotPositionXYById(slotId)
					}
					props = {
						key : slotId+'__'+selectedComponentDetails.componentMultimediaURL,
						id : slotId+'__'+selectedComponentDetails.componentMultimediaURL,
						radius : '3',
						cx : slotPosition.x,
						cy : slotPosition.y,
						color : selectedOptionDetails.color,
						blink : false
					}
				} else {
					// console.log('exists --> optionId slotId', optionId, slotId);
					props = JSON.parse(JSON.stringify(blinkDotList[index].props))
					let key = JSON.parse(JSON.stringify(blinkDotList[index].key))
					Object.assign(
						props,
						{
							blink : false,
							color : selectedOptionDetails.color,
							key : key
						}
					)
				}
				renderUpdatedBlinkDots.push(
					<BlinkDot {...props}/>
				)
			}
		}
		this.setState({
			renderBlinkDots : renderUpdatedBlinkDots
		}, function () {
			// console.log('updated renderBlinkDots');
		})
	}

	getAllSlotPositionsByComponent (component) {
		let slotsPositionXYList = []
		if (component !== undefined && component !== null) {
			let componentOptions = component.componentOptions
			if (componentOptions !== undefined && componentOptions !== null) {
				for (let i=0;i<componentOptions.length;i++) {
					let slots = componentOptions[i].slots;
					if (slots !== undefined && slots !== null) {
						for (let j=0;j<slots.length;j++) {
							let slotId = getSlotIdByName(slots[j].slot)
							if (slotId === -1) {
								alert ('Unrecognised slot given')
								return
							}
							// console.log('getComponentSlotPositionById called getAllSlotPositionsByComponent');
							let slotPosition = slotId.startsWith('AR') ? getComponentSlotPositionById('svgPanel', slotId) : getSlotPositionXYById(slotId)
							slotPosition.optionId = componentOptions[i].optionId
							slotsPositionXYList.push(
								slotPosition
							)
						}
					}
				}
			}
		}
		return slotsPositionXYList
	}

	adjustClickPositionToSlotPosition (clickPosition) {
		let position = {}
		if (clickPosition !== undefined && clickPosition !== null) {
			position.x = ( (clickPosition.x % 10) < 5) ? Math.floor(clickPosition.x / 10)  * 10 : Math.ceil(clickPosition.x / 10) * 10
			position.y = ( (clickPosition.y % 10) < 2.5) ? Math.floor(clickPosition.y / 5) * 5 : Math.ceil(clickPosition.y / 5) * 5
		}
		return position
	}

	adjustClickPositionToGivenSlotsPosition (clickPosition, selectedComponentDetails) {
		let slotsPositionXYList = this.getAllSlotPositionsByComponent(selectedComponentDetails)
		return this.findNearestPosition(clickPosition, slotsPositionXYList, selectedComponentDetails)
	}

	/*findNearestPosition (clickPosition, availablePositionsList) {
		let minDistance = Number.MAX_VALUE,
			calculatedDistance = 0,
			minDistancePositionIndex = 0
		if (availablePositionsList !== undefined && availablePositionsList !== null) {
			for(let i=0;i<availablePositionsList.length;i++) {
				calculatedDistance = getDistanceBetweenTwoPoints(clickPosition, availablePositionsList[i])
				if (calculatedDistance < minDistance) {
					minDistance = calculatedDistance
					minDistancePositionIndex = i
				}
			}
		}
		let nearestPosition = availablePositionsList[minDistancePositionIndex]
		this.props.IoTyActions.selectCircuitOption(nearestPosition.optionId)
		this.selectedComponentOptionId = nearestPosition.optionId
		return nearestPosition
	}*/
	findNearestPosition (clickPosition, availablePositionsList, selectedComponentDetails) {
		let minDistance = Number.MAX_VALUE,
			calculatedDistance = 0,
			minDistancePositionIndex = 0,
			// minDistanceOptions = [],
			list = []
		if (this.mouseClicksCount === 1) {
			list = availablePositionsList
		} else if (this.mouseClicksCount === 2) {
			list = this.minDistancePositions
		}
		if (list !== undefined && list !== null) {
			for(let i=0;i<list.length;i++) {
				calculatedDistance = getDistanceBetweenTwoPoints(clickPosition, list[i])
				// console.log('calculatedDistance, minDistance ', calculatedDistance, minDistance);
				if (calculatedDistance < minDistance) {
					minDistance = calculatedDistance
					minDistancePositionIndex = i
				}
				// console.log('minDistanceOptions', minDistanceOptions);
			}
		}
		let nearestPosition = list[minDistancePositionIndex]
		if (selectedComponentDetails.componentMultimediaURL.startsWith('#')) {
			let componentOptions = selectedComponentDetails.componentOptions
			for (let i=0;i<componentOptions.length;i++) {
				let slots = componentOptions[i].slots
				for (let j=0;j<slots.length;j++) {
					let slotId = getSlotIdByName(slots[j].slot),
						slotPosition = null
					if (slotId.startsWith('AR') || slotId.startsWith('relay')) {
						slotPosition = getComponentSlotPositionById('svgPanel', slotId)
					} else {
						slotPosition = getSlotPositionXYById(slotId)
					}
					if (nearestPosition.x === slotPosition.x && nearestPosition.y === slotPosition.y) {
						slotPosition.optionId = componentOptions[i].optionId
						this.minDistanceOptions.push(slotPosition)
					}
				}
			}
			// console.log('nearestPosition', this.minDistanceOptions, nearestPosition);
			for (let i=0;i<this.minDistanceOptions.length;i++) {
				// console.log('componentOptions', componentOptions, this.minDistanceOptions[i]);
				let selectedOptionDetails = getObjectById(componentOptions, 'optionId', this.minDistanceOptions[i].optionId)
				// console.log('selectedOptionDetails', selectedOptionDetails);
				let slots = selectedOptionDetails.slots
				for (let j=0;j<slots.length;j++) {
					let slotId = getSlotIdByName(slots[j].slot),
						slotPosition = null
					if (slotId.startsWith('AR') || slotId.startsWith('relay')) {
						slotPosition = getComponentSlotPositionById('svgPanel', slotId)
					} else {
						slotPosition = getSlotPositionXYById(slotId)
					}
					slotPosition.optionId = this.minDistanceOptions[i].optionId
					this.minDistancePositions.push(slotPosition)
				}
			}
			// console.log('minDistancePositions >> ', this.minDistancePositions);
			// console.log('mouseClicksCount',  this.mouseClicksCount);
			if (this.mouseClicksCount > 0 && this.mouseClicksCount <= 2) {
				// console.log('displaySlots called');
				for (let i=0;i<this.minDistanceOptions.length;i++) {
					this.displaySlots(this.state.renderBlinkDots, this.minDistanceOptions[i].optionId, selectedComponentDetails)
				}
				if (this.mouseClicksCount === 2) {
					this.props.IoTyActions.selectCircuitOption(nearestPosition.optionId)	
				}
			}
			this.selectedComponentOptionId = nearestPosition.optionId
			
		} else {
			this.props.IoTyActions.selectCircuitOption(nearestPosition.optionId)
		}
		return nearestPosition
	}

	render() {
		let {IoTyvLab, IoTyActions, selectedComponent} = this.props
		let BreadBoardProps = {}
		BreadBoardProps.selectedComponent = selectedComponent
		return (
			<div>
				<img src="/images/Loading.png" alt="Loading icon" className='ioty-circuit-loader'/>
				<svg id='svgPanel' onClick={this.clickHandler} style={{minHeight : this.relay === null ? '500px' : '700px'}}>
					<BreadBoard 
						setMouseXY={this.setMouseXY}/>
					{this.arduino}
					{this.relay}
					{this.state.renderConnectionWires}
					{this.state.renderBlinkDots}
				</svg>
				{this.state.renderExistedCircuitData}
				{this.state.renderNewCircuitData}
			</div>

		);
	}
}