let penModel;
let thighModel;
let hidePlane;

let camera;
let aspectRatio;
let dragElement;
let sceneLoaded;

let overlay;
let overlayCloseButton
let activeOverlayContent;

let injectionSitesOverlay;
let overviewOverlay;
let storageOverlay;
let disposalOverlay;
let referencesOverlay;

let penExpandedUI;
let penCollapsedUI;

let expandToggle;
let wireframeButton;
let exploreButton;
let qrCodeButton;
let savingsCardButton;
let savingsCardButton2;
let injectionSitesButton;

let overviewButton;
let storageButton;
let disposalButton;
let referencesButton;

// Mobile
let isMobile;
let mobileMenuButton;
let mobileNavContainer;
let mobileStateButtons;
let mobileMenuButtons;

let overviewButtonMobile
let storageButtonMobile 
let disposalButtonMobile

let swipeTextDesktop;
let swipeTextMobile;
let exploreSwipeSubtitle;
let exploreClickDragSubtitle;

function uiState() {
    this.state = '';
    this.button = null;
	this.stateUI = null;
	this.stateSteps = {};
	this.stepProgress = 0;
	this.stepAnimations = {};
	this.swipeToProgress = true;
	this.canInteract = false;
    this.clipName = '';
    this.audio = '';
}

function stepAnimation(_modelAnim = '', _penPosition = null, _speed = 1, _repetitions = 1, _postMove = false, _hasArrow = '', _timerAnim = false, _callback = null) {
	this.modelAnim = _modelAnim;
	this.penPosition = _penPosition;
	this.speed = _speed;
	this.repetitions = _repetitions;
	this.postMove = _postMove;
	this.hasArrow = _hasArrow;
	this.timerAnim = _timerAnim;
	this.callback = _callback;
}

let NewCallback;
let positionTween;
let lastAnimation = '';

var basePosition = {x:0, y:1, z:-2};
let farRadius = 15.2;
let closeRadius = 14;
let phi = 1.571;
let theta = 0;

let mixGraphics;
let timerCircle;
let timerCounter;
let timerText;
let timerSetTimeout;
let arrowSetTimeout;
let thighShown = false;
let penShown = true;

let startUI;
let startButton;
let startISI;
let stateButtonGroup;
let nextStepButtons;

let mixState = new uiState;
let unlockState = new uiState;
let unscrewState = new uiState;
let injectState = new uiState;
let exploreState = new uiState;
// let isiState = new uiState;
let savingsState = new uiState;
// let qiState = new uiState;

// Veeva States
// let states = [
// 	mixState, 
// 	unlockState, 
// 	unscrewState, 
// 	injectState, 
// 	exploreState,
// 	isiState,
// 	qiState
// ];

// Web States
let states = [
	mixState, 
	unlockState, 
	unscrewState, 
	injectState, 
	exploreState,
	savingsState
];

let currentState = 0;
let isHome = true;

let xDown = null;
let yDown = null;
let swipeDir = 0;
let exploded = false;
let mouseDown = false;

let buttonClickAudio;
let penClickAudio;

function init() {
	// Get A-Frame Assets
	aspectRatio = window.innerWidth / window.innerHeight;
	swipeTextDesktop = document.getElementsByClassName('swipe-text');
	swipeTextMobile = document.getElementsByClassName('swipe-text-mobile');
	exploreSwipeSubtitle = document.getElementById('exploreSwipeSubtitle');
	exploreClickDragSubtitle = document.getElementById('exploreClickDragSubtitle');
	if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
		// true for mobile device
		isMobile = true;
		for (let i = 0; i < swipeTextMobile.length; i++)
		{
			swipeTextMobile[i].classList.remove('hidden');
		}
		exploreSwipeSubtitle.classList.remove('hidden');
		console.log("mobile device");
	}
	else {
		// false for not mobile device
		isMobile = false;
		for (let i = 0; i < swipeTextDesktop.length; i++)
		{
			swipeTextDesktop[i].classList.remove('hidden');
		}
		exploreClickDragSubtitle.classList.remove('hidden');
		console.log("not mobile device");
	}

	mixGraphics = [];
	mixGraphics[0] = document.getElementById('mixTimerGraphic1');
	mixGraphics[1] = document.getElementById('mixTimerGraphic2');
	mixGraphics[2] = document.getElementById('mixTimerGraphic3');
	mixGraphics[3] = document.getElementById('mixTimerGraphic4');
	mixGraphics[4] = document.getElementById('mixTimerGraphic5');
	mixGraphics[5] = document.getElementById('mixTimerGraphic6');
	mixGraphics[6] = document.getElementById('mixTimerGraphic7');

	var sceneEl = document.querySelector('a-scene');
	camera = sceneEl.querySelector('#camera');
	penModel = sceneEl.querySelector('#pen-model');
	thighModel = sceneEl.querySelector('#thigh-model');
	hidePlane = sceneEl.querySelector('#hidePlane');
	buttonClickAudio = sceneEl.querySelector("#uiAudio");
	penClickAudio = sceneEl.querySelector("#penClick");

	// Various UI buttons
	penExpandedUI = document.getElementById('penExpandedUI');
	penCollapsedUI = document.getElementById('penCollapsedUI');
	dragElement = document.getElementById('dragElement');
	// qrCodeGraphic = document.getElementById('qrCodeGraphic');
	// logo = document.getElementById('logo');
	allButtons = document.getElementsByClassName('button-click');

	// Various UI buttons
	expandToggle = document.getElementById('expandToggle');
	startButton = document.getElementById('startButton');
	// startISI = document.getElementById('startISI');
	wireframeButton = document.getElementById('wireframeButton');
	exploreButton = document.getElementById('exploreButton');
	// qrCodeButton = document.getElementById('qrCodeButton');
	savingsCardButton = document.getElementById('savingsCardButton');
	savingsCardButton2 = document.getElementById('savingsCardButton2');
	savingsCard = document.getElementById('savingsCard');
	injectionSitesButton = document.getElementById('injectionSitesButton');

	// Overlay and Content
	overlay = document.getElementById('overlay');
	overlayCloseButton = document.getElementById('overlayCloseButton');

	injectionSitesOverlay = document.getElementById('injectionSitesOverlay');
	// piOverlay = document.getElementById('piOverlay');
	// instructionsOverlay = document.getElementById('instructionsOverlay');
	overviewOverlay = document.getElementById('overviewOverlay');
	storageOverlay = document.getElementById('storageOverlay');
	disposalOverlay = document.getElementById('disposalOverlay');
	referencesOverlay = document.getElementById('referencesOverlay');
	activeOverlayContent = overviewOverlay;

	// Nav Buttons
	// cvaButton = document.getElementById('cvaButton');
	// safetyButton = document.getElementById('safetyButton');
	// piButton = document.getElementById('piButton');
	// instructionsButton = document.getElementById('instructionsButton');
	overviewButton = document.getElementById('overviewButton');
	storageButton = document.getElementById('storageButton');
	disposalButton = document.getElementById('disposalButton');
	overviewButtonMobile = document.getElementById('overviewButtonMobile');
	storageButtonMobile = document.getElementById('storageButtonMobile');
	disposalButtonMobile = document.getElementById('disposalButtonMobile');
	// referencesButton = document.getElementById('referencesButton');

	mobileMenuButton = document.getElementById('mobileMenuButton');
	mobileNavContainer = document.getElementById('mobileNavContainer');
	mobileStateButtons = document.getElementsByClassName('mobile-state-button');
	mobileMenuButtons = document.getElementsByClassName('mobile-nav-button');

	stateButtonGroup = document.getElementById('states');
	stateButtons = document.getElementsByClassName('state-button');
	startUI = document.getElementById('welcome');

	nextStepButtons = document.getElementsByClassName('next-step-button')
	positionTween = new TWEEN.Tween();
	
	startButton.addEventListener('click', function(e) {
		startUI.classList.add('hidden');
		dragElement.classList.remove('hidden');
		stateButtonGroup.classList.remove('stowed');
		// logo.classList.add('stowed');
		// isHome = false;
		SetState(0);
		PlayAnimation('StandUp', 1, 2);
		TweenPenPosition(states[0].stepAnimations[0]);
	});

	homeButton.addEventListener('click', function(e) {
		HideCurrentState();
		startUI.classList.remove('hidden');
		dragElement.classList.add('hidden');
		stateButtonGroup.classList.add('stowed');
		// logo.classList.remove('stowed');
		isHome = true;
		PlayAnimation('IdleLying', 1, 2);
		aspectRatio = GetAspectRatio();
		if(aspectRatio > (12/10))
		{
			TweenPenPosition({penPosition: {x:0, y:-.5, z:0}});
		}
		else 
		{
			TweenPenPosition({penPosition: {x:0, y:-(1.5/aspectRatio), z:-(5/aspectRatio)}});
		}
	});

	aspectRatio = GetAspectRatio();
	sceneLoaded = false;
	sceneEl.addEventListener('loaded', function() {
		if(!sceneLoaded)
		{
			if(aspectRatio > (12/10))
			{
				TweenPenPosition({penPosition: {x:0, y:-.5, z:0}});
			}
			else 
			{
				TweenPenPosition({penPosition: {x:0, y:-(1.5/aspectRatio), z:-(5/aspectRatio)}});
				SetPenPosition({x:0, y:-(1.2/aspectRatio), z:-(5/aspectRatio)})
			}
			for(let c = 0; c < allButtons.length; c++)
			{
				allButtons[c].addEventListener('click', function(e)
				{
					buttonClickAudio.components.sound.playSound();
				});
				allButtons[c].classList.remove("no-pointer-events");
				allButtons[c].classList.add("pointer-events");
			}
		}
		sceneLoaded = true;
	})
	setTimeout( function() {
		if(!sceneLoaded)
		{
			if(aspectRatio > (12/10))
			{
				TweenPenPosition({penPosition: {x:0, y:-.5, z:0}});
			}
			else 
			{
				TweenPenPosition({penPosition: {x:0, y:-(1.5/aspectRatio), z:-(5/aspectRatio)}});
				SetPenPosition({x:0, y:-(1.2/aspectRatio), z:-(5/aspectRatio)})
			}
			for(let c = 0; c < allButtons.length; c++)
			{
				allButtons[c].addEventListener('click', function(e)
				{
					buttonClickAudio.components.sound.playSound();
				});
				allButtons[c].classList.remove("no-pointer-events");
				allButtons[c].classList.add("pointer-events");
			}
		}
		sceneLoaded = true;
	}, 3000);

	window.addEventListener('resize', RepositionOnResize);

	mobileMenuButton.addEventListener('click', function() { ToggleMobileMenu(); });
	for (let i = 0; i < mobileMenuButtons.length; i++)
	{
		mobileMenuButtons[i].addEventListener('click', function() { ToggleMobileMenu(); });
	}

	// startISI.addEventListener('click', function(e) {
	// 	startUI.classList.add('hidden');
	// 	dragElement.classList.remove('hidden');
	// 	stateButtonGroup.classList.remove('stowed');
	// 	logo.classList.add('stowed');
	// 	SetState(4);
	// });

	states[4].swipeToProgress = false;
	states[5].swipeToProgress = false;
	// states[6].swipeToProgress = false;

	states[4].canInteract = true;

	// State 1 Step Animations
	state1Step1 = new stepAnimation('IdleStanding', basePosition, 2);
	state1Step2 = new stepAnimation('Shake', basePosition, 1, Infinity, false, '', true);
	state1Step3 = new stepAnimation('IdleStanding', basePosition);

	states[0].stepAnimations = [
		state1Step1, state1Step2, state1Step3
	];

	// State 2 Step Animations
	state2Step1 = new stepAnimation('IdleStanding', basePosition, 1, 1, false);
	state2Step2 = new stepAnimation('Unlock', {x:0, y:2.5, z:8}, 1.1, 1, false, 'lockB', false, ProgressState);
	state2Step3 = new stepAnimation('IdleStandingUnlocked', basePosition);

	states[1].stepAnimations = [
		state2Step1, state2Step2, state2Step3
	];

	// State 3 Step Animations
	state3Step1 = new stepAnimation('IdleStandingUnlocked', basePosition, 1, 1, false);
	state3Step2 = new stepAnimation('Unscrew', {x:0, y:-.2, z:8}, 1, 1, true, 'capB', false, ProgressState);
	state3Step3 = new stepAnimation('IdleUnscrewed', basePosition);

	states[2].stepAnimations = [
		state3Step1, state3Step2, state3Step3
	];

	// State 4 Step Animations
	state4Step1 = new stepAnimation('InjectFlip', {x:0, y:1.2, z:-2}, 1.5);
	state4Step2 = new stepAnimation('Inject', {x:0, y:1, z:-2}, 1, 1, false, '', false, ProgressState);
	state4Step3 = new stepAnimation('Plunge', {x:0, y:1, z:-2}, 1, 1, false, '', true);
	state4Step4 = new stepAnimation('Lift', {x:0, y:1.2, z:-2});

	states[3].stepAnimations = [
		state4Step1, state4Step2, state4Step3, state4Step4
	];

	// ISI
	// State 5 Step Animations
	// state5Step1 = new stepAnimation('', {x:0, y:1, z:-2});

	// states[4].stepAnimations = [
	// 	state5Step1
	// ];

	// Explore
	// State 5 Step Animations
	state5Step1 = new stepAnimation('Implode', {x:0, y:.7, z:2});
	state5Step2 = new stepAnimation('Explode', {x:.7, y:.7, z:2});

	states[4].stepAnimations = [
		state5Step1, state5Step2
	];

	// Savings Card
	// State 7 Step Animations
	state6Step1 = new stepAnimation('IdleLying', {x:0, y:-1.5, z:-3});

	states[5].stepAnimations = [
		state6Step1
	];

	// QR Code
	// State 7 Step Animations
	// state7Step1 = new stepAnimation('IdleLying', {x:0, y:-.52, z:0});

	// states[6].stepAnimations = [
	// 	state7Step1
	// ];


	for (let i = 0; i < states.length; i++)
	{
		states[i].button = stateButtons[i];
		states[i].button.addEventListener('click', function(e) {
			SetState(i);
		});
		states[i].stateUI = document.getElementsByClassName('state-' + (i+1));
		stateSteps = document.querySelectorAll("[class*='state-" + (i+1) + "-step']");
		states[i].stateSteps = Array.from(stateSteps);
	}

	for (let i = 0; i < mobileStateButtons.length; i++)
	{
		mobileStateButtons[i].addEventListener('click', function(e) {
			if(!startUI.classList.contains('hidden')) {
				startUI.classList.add('hidden');
				dragElement.classList.remove('hidden');
				stateButtonGroup.classList.remove('stowed');
			}
			SetState(i);
		});
	}

	timerCounter = document.getElementById('timerCounter');
	timerText = document.getElementById('timerText');
	timerCircle = new ProgressBar.Circle('#indicatorContainer', {
		strokeWidth: 5,
		color: '#00693C',
		trailWidth: 5,
		trailColor: '#00693c4d',
	});
	timerCircle.text = timerText;

	for (let i = 0; i < nextStepButtons.length; i++)
	{
		nextStepButtons[i].addEventListener('click', function(e) {
			NextState();
		})
	}

	dragElement.addEventListener('touchstart', handleTouchStart, false);
	dragElement.addEventListener('touchmove', handleTouchMove, false);
	dragElement.addEventListener('touchend', handleTouchEnd, false);

	dragElement.addEventListener('mousedown', handleMouseDown, false);
	dragElement.addEventListener('mousemove', handleMouseMove, false);
	dragElement.addEventListener('mouseup', handleTouchEnd, false);

	document.addEventListener('mousedown', function() {
		mouseDown = true;
	})
	document.addEventListener('mouseup', function() {
		mouseDown = false;
	})

	document.addEventListener('mousemove', function (evt) {
		if(mouseDown && currentState == 4 && (!penCollapsedUI.classList.contains('hidden') || !penExpandedUI.classList.contains('hidden')))
		{
			penCollapsedUI.classList.add('hidden');
			penExpandedUI.classList.add('hidden');
		}
	});
	document.addEventListener('touchmove', function () {
		if(currentState == 4 && (!penCollapsedUI.classList.contains('hidden') || !penExpandedUI.classList.contains('hidden')))
		{
			penCollapsedUI.classList.add('hidden');
			penExpandedUI.classList.add('hidden');
		}
	});

	injectionSitesButton.addEventListener('click', function(e) {
		activeOverlayContent.classList.add('hidden');
		activeOverlayContent = injectionSitesOverlay;
		injectionSitesOverlay.classList.remove('hidden');
		overlay.classList.remove('hidden');
	});

	overviewButton.addEventListener('click', function(e) {
		ShowOverviewOverlay();
	});

	overviewButtonMobile.addEventListener('click', function(e) {
		ShowOverviewOverlay();
	});

	storageButton.addEventListener('click', function(e) {
		ShowStorageOverlay();
	});

	storageButtonMobile.addEventListener('click', function(e) {
		ShowStorageOverlay();
	});

	disposalButton.addEventListener('click', function(e) {
		ShowDisposalOverlay();
	});

	disposalButtonMobile.addEventListener('click', function(e) {
		ShowDisposalOverlay();
	});

	// referencesButton.addEventListener('click', function(e) {
	// 	activeOverlayContent = referencesOverlay;
	// 	referencesOverlay.classList.remove('hidden');
	// 	overlay.classList.remove('hidden');
	// });
	
	overlayCloseButton.addEventListener('click', function(e) {
		overlay.classList.add('hidden');
		activeOverlayContent.classList.add('hidden');
	});

	exploreButton.addEventListener('click', function(e) {
		SetState(4)
	});

	// qrCodeButton.addEventListener('click', function(e) {
	// 	SetState(6)
	// });

	savingsCardButton.addEventListener('click', function(e) {
		SetState(5)
	});
	savingsCardButton2.addEventListener('click', function(e) {
		SetState(5)
	});

	expandToggle.addEventListener('click', function(e) {
		ToggleExpand();
	});

	for(let c = 0; c < allButtons.length; c++)
	{
		allButtons[c].classList.remove("pointer-events");
		allButtons[c].classList.add("no-pointer-events");
	}
}

function ToggleMobileMenu() {
	if(mobileNavContainer.classList.contains('collapsed')) {
		mobileNavContainer.classList.remove('collapsed');
		mobileMenuButton.classList.add('close');
	}
	else {
		mobileNavContainer.classList.add('collapsed');
		mobileMenuButton.classList.remove('close');
	}
}

function OnStartExperience() {
	camera.setAttribute("orbit-controls-kitmod", {
		rotateToSet: true
	});
}

function ShowOverviewOverlay() {
	activeOverlayContent.classList.add('hidden');
	activeOverlayContent = overviewOverlay;
	overviewOverlay.classList.remove('hidden');
	overlay.classList.remove('hidden');
}

function ShowStorageOverlay() {
	activeOverlayContent.classList.add('hidden');
	activeOverlayContent = storageOverlay;
	storageOverlay.classList.remove('hidden');
	overlay.classList.remove('hidden');
}

function ShowDisposalOverlay() {
	activeOverlayContent.classList.add('hidden');
	activeOverlayContent = disposalOverlay;
	disposalOverlay.classList.remove('hidden');
	overlay.classList.remove('hidden');
}

function getTouches(evt) {
	return evt.touches || evt.originalEvent.touches;
}                                                     
  
function handleTouchStart(evt) {
	const firstTouch = getTouches(evt)[0];                                      
	xDown = firstTouch.clientX;                                      
	yDown = firstTouch.clientY;                                      
};

function handleMouseDown(evt) {
	xDown = evt.clientX;                                      
	yDown = evt.clientY;                                      
};

function handleTouchMove(evt) {
    if ( ! xDown || ! yDown ) {
        return;
    }

    var xUp = evt.touches[0].clientX;                                    
    var yUp = evt.touches[0].clientY;

    var xDiff = xDown - xUp;
    var yDiff = yDown - yUp;

    if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
        if ( xDiff > 0 ) {
			/* left swipe */
			swipeDir = 1;
        } else {
			/* right swipe */
			swipeDir = 2;
        }                       
    } else {
        if ( yDiff > 0 ) {
			/* up swipe */
			swipeDir = 3;
        } else { 
			/* down swipe */
			swipeDir = 4;
        }                                                                 
	}
    /* reset values */
	xDown = null;
	yDown = null;
	
};

function handleMouseMove(evt) {
    if ( ! xDown || ! yDown ) {
        return;
    }

    var xUp = evt.clientX;                                    
    var yUp = evt.clientY;

    var xDiff = xDown - xUp;
    var yDiff = yDown - yUp;

    if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
        if ( xDiff > 0 ) {
			/* left swipe */
			swipeDir = 1;
        } else {
			/* right swipe */
			swipeDir = 2;
        }                       
    } else {
        if ( yDiff > 0 ) {
			/* up swipe */
			swipeDir = 3;
        } else { 
			/* down swipe */
			swipeDir = 4;
        }                                                                 
	}
    /* reset values */
	xDown = null;
	yDown = null;
	
};

function handleTouchEnd() {
	if(swipeDir == 1) {
		/* left swipe */
		if(currentState == 1 && states[1].stepProgress == 0) {
			ProgressState();
		}
	}
	else if(swipeDir == 2) {
		/* right swipe */
		if(currentState == 2 && states[2].stepProgress == 0) {
			ProgressState();
		}
	}
	else if(swipeDir == 3 || swipeDir == 4) {
		/* up or down swipe */
		if(currentState == 0 && states[0].stepProgress == 0) {
			ProgressState();
		}
		if(swipeDir == 4 && currentState == 3 && states[3].stepProgress == 0) {
			ProgressState();
		}
	}
	swipeDir = 0;
}

function NextState() {
	SetState(currentState + 1);
}

function SetState(newState)
{
	isHome = false;
	var lastState = currentState;
	var uiState = states[lastState];
	currentState = newState;
	if(newState == 4) {
		CollapsePen();
	}
	penModel.removeEventListener('animation-finished', NewCallback);
	clearTimeout(timerSetTimeout);
	clearTimeout(arrowSetTimeout);
	timerCircle.stop();
	positionTween.stop();
	if(uiState.stepAnimations[uiState.stepProgress].hasArrow !== '')
	{
		SetArrow(uiState.stepAnimations[uiState.stepProgress].hasArrow, 0, 100);
	}
	DisableStateButtons();
	// DisableArrows();
	DisableStateUI(lastState);
	DisableStateSteps(lastState);
	uiState.button.classList.remove('selected');

	uiState = states[newState];
	DisableStateSteps(newState);
	EnableStateUI(newState);
	uiState.button.classList.add('selected');

	CheckForStateAnimation();
	arrowSetTimeout = setTimeout(function() {
		if(uiState.stepAnimations[uiState.stepProgress].hasArrow !== '')
		{
			SetArrow(uiState.stepAnimations[uiState.stepProgress].hasArrow, 1, 10);
		}
	}, 50);

	if(uiState.canInteract) {
		aspectRatio = GetAspectRatio();
		if(aspectRatio > (12/10))
		{
			console.log("WideAspect: " + aspectRatio);
			camera.setAttribute('orbit-controls-kitmod', {
				enableZoom: true,
				enableRotate: true,
				rotateToSet: true,
				rotateTo: closeRadius + " " + phi + " " + theta,
			})
		}
		else
		{
			console.log("TallAspect: " + aspectRatio);
			camera.setAttribute('orbit-controls-kitmod', {
				enableZoom: true,
				enableRotate: true,
				rotateToSet: true,
				rotateTo: (farRadius + (8/aspectRatio)) + " " + phi + " " + theta,
			})
		}
	} else {
		camera.setAttribute('orbit-controls-kitmod', {
			enableZoom: false,
			enableRotate: false,
			rotateToSet: true,
			rotateTo: farRadius + " " + phi + " " + theta,
		})
	}
	if(uiState.swipeToProgress) {
		dragElement.classList.remove('hidden');
	} else {
		dragElement.classList.add('hidden');
	}
}

function ProgressState()
{
	penModel.removeEventListener('animation-finished', NewCallback);
	clearTimeout(timerSetTimeout);
	clearTimeout(arrowSetTimeout);
	timerCircle.stop();
	var uiState = states[currentState];
	if(uiState.stepAnimations[uiState.stepProgress].hasArrow !== '')
	{
		SetArrow(uiState.stepAnimations[uiState.stepProgress].hasArrow, 0, 50);
	}
	nextStep = uiState.stateSteps.filter(element => element.classList.contains('state-' + (currentState+1) + '-step-' + (uiState.stepProgress+2)));
	if(nextStep.length > 0)
	{
		currentStep = uiState.stateSteps.filter(element => element.classList.contains('state-' + (currentState+1) + '-step-' + (uiState.stepProgress+1)));
		currentStep.forEach(el => el.classList.add('hidden'));
		nextStep.forEach(el => el.classList.remove('hidden'));
		uiState.stepProgress += 1;
	}
	CheckForStateAnimation();

	if(uiState.stepAnimations[uiState.stepProgress].timerAnim)
	{
		TimerAnimation();
	}

	arrowSetTimeout = setTimeout(function() {
		if(uiState.stepAnimations[uiState.stepProgress].hasArrow !== '')
		{
			SetArrow(uiState.stepAnimations[uiState.stepProgress].hasArrow, 1, 10);
		}
	}, 50);
}

function PreviousState()
{
	var uiState = states[currentState];
	previousStep = uiState.stateSteps.filter(element => element.classList.contains('state-' + (currentState+1) + '-step-' + (uiState.stepProgress)));
	if(previousStep.length > 0)
	{
		currentStep = uiState.stateSteps.filter(element => element.classList.contains('state-' + (currentState+1) + '-step-' + (uiState.stepProgress+1)));
		currentStep.forEach(el => el.classList.add('hidden'));
		previousStep.forEach(el => el.classList.remove('hidden'));
		uiState.stepProgress -= 1;
	}
	CheckForStateAnimation();
}

function EnableStateUI(state)
{
	var uiState = states[state];
	for (i = 0; i < uiState.stateUI.length; i++) {
		uiState.stateUI[i].classList.remove('hidden');
	}
	if(state == 0)
	{
		for(var i = 0; i < mixGraphics.length; i++)
		{
			mixGraphics[i].style.opacity = 1;
		}
	}
	ResetState(uiState, state)
}

function DisableStateUI(state)
{
	var uiState = states[state];
	for (i = 0; i < uiState.stateUI.length; i++) {
		uiState.stateUI[i].classList.add('hidden');
	}
}

function DisableStateSteps(state)
{
	var uiState = states[state];
	for (i = 0; i < uiState.stateSteps.length; i++) {
		uiState.stateSteps[i].classList.add('hidden');
	}
}

function DisableStateButtons() {
	for (i = 0; i < stateButtons.length; i++) {
		stateButtons[i].classList.remove('selected');
	}
}

function ResetState(uiState, state) {
	step1 = uiState.stateSteps.filter(element => element.classList.contains('state-' + (state+1) + '-step-1'));
	step1.forEach(el => el.classList.remove('hidden'));
	uiState.stepProgress = 0;
}

function HideCurrentState()
{
	var uiState = states[currentState];
	penModel.removeEventListener('animation-finished', NewCallback);
	clearTimeout(timerSetTimeout);
	clearTimeout(arrowSetTimeout);
	timerCircle.stop();
	positionTween.stop();
	camera.setAttribute('orbit-controls-kitmod', {
		rotateTo: 12 + " " + phi + " " + theta,
	})
	if(uiState.stepAnimations[uiState.stepProgress].hasArrow !== '')
	{
		SetArrow(uiState.stepAnimations[uiState.stepProgress].hasArrow, 0, 100);
	}
	DisableStateButtons();
	DisableStateUI(currentState);
	DisableStateSteps(currentState);
	uiState.button.classList.remove('selected');
}

function ToggleExpand()
{
	if(exploded === false){
		ExplodePen();
		ProgressState();
	} else {
		CollapsePen();
		PreviousState();
	} 
	aspectRatio = GetAspectRatio();
	camera.setAttribute('orbit-controls-kitmod', {rotateToSet: false});
	if(aspectRatio > (12/10))
	{
		console.log("reset view");
		camera.setAttribute('orbit-controls-kitmod', {
			rotateToSet: true,
			rotateToSpeed: 0.08,
			rotateTo: closeRadius + " " + phi + " " + theta,
		})
	}
	else
	{
		console.log("reset view");
		camera.setAttribute('orbit-controls-kitmod', {
			rotateToSet: true,
			rotateToSpeed: 0.08,
			rotateTo: (farRadius + (8/aspectRatio)) + " " + phi + " " + theta,
		})
	}
	setTimeout(function() {
		camera.setAttribute('orbit-controls-kitmod', {rotateToSet: false});
	}, 1000)
}

function PlayAnimation(animationClip, repetitions = 1, animSpeed = 1, callback = null)
{
	if(lastAnimation != animationClip)
	{
		if(animationClip == "Inject") { ThighInjectionAnimation() }
		penModel.removeAttribute('animation-mixer');
		console.log("Playing: " + animationClip);
		lastAnimation = animationClip;
		penModel.setAttribute('animation-mixer', {
			clip: animationClip,
			loop: 'repeat',
			timeScale: animSpeed,
			repetitions: repetitions,
			clampWhenFinished: true,
			crossFadeDuration: .4
		});
		if(callback != null)
		{
			penModel.addEventListener('animation-finished', NewCallback = function() {
				// console.log('Callback triggered');
				if(animationClip == "Inject")
				{
					setTimeout(function()
					{
						callback();
					}, 300);
				}
				else
				{
					callback();
				}
				penModel.removeEventListener('animation-finished', arguments.callee); 
			});
		}
		if(animationClip == "Inject")
		{
			setTimeout(function() {
				penClickAudio.components.sound.playSound();
			}, 1600);
		}
		if(animationClip == "Unlock")
		{
			setTimeout(function() {
				penClickAudio.components.sound.playSound();
			}, 3500);
		}
	}
}

function CheckForStateAnimation()
{
	var uiStateAnimations = states[currentState].stepAnimations[states[currentState].stepProgress];
	if(!uiStateAnimations.postMove && uiStateAnimations.modelAnim != '')
	{
		PlayAnimation(
			uiStateAnimations.modelAnim, 
			uiStateAnimations.repetitions,
			uiStateAnimations.speed,
			uiStateAnimations.callback
		);
	}
	if(currentState == 3  && !thighShown) {
		ShowThigh(); 
	}
	else if(currentState == 3 && states[3].stepProgress == 3 && thighShown) {
		HideThigh();
	}
	else if(currentState != 3 && thighShown) {
		HideThigh();
	}
	if(currentState == 5 && penShown) {
		if((aspectRatio < (12/10)) || (aspectRatio > (22/9)))
		{
			HidePen(); 
		}
	}
	else if(currentState != 5 && !penShown) {
		ShowPen();
	}
	if(currentState == 0 && states[0].stepProgress == 1)
	{
		for(var i = 0; i < mixGraphics.length; i++)
		{
			FadeOutElement(mixGraphics[i], 600*(i));
		}
	}
	if(uiStateAnimations.penPosition != null)
	{
		TweenPenPosition(uiStateAnimations);
	}
}

function TweenPenPosition(stateAnimations)
{
	position = { 
		x: penModel.object3D.position.x,
		y: penModel.object3D.position.y,
		z: penModel.object3D.position.z
	}
	positionTween = new TWEEN.Tween( position )
	.to({ 
		x: stateAnimations.penPosition.x, 
		y: stateAnimations.penPosition.y, 
		z: stateAnimations.penPosition.z 
	}, 500)
	.easing( TWEEN.Easing.Cubic.InOut )
	.onUpdate(function() {
		penModel.object3D.position.x = position.x;
		penModel.object3D.position.y = position.y;
		penModel.object3D.position.z = position.z;
	})
	.onComplete(function() {
		if(stateAnimations.postMove && stateAnimations.modelAnim != '')
		{
			// console.log("On Tween Complete");
			PlayAnimation(
				stateAnimations.modelAnim, 
				stateAnimations.repetitions,
				stateAnimations.speed,
				stateAnimations.callback
			);
		}
	})
	positionTween.start();
}

function SetPenPosition(newPosition)
{
	// console.log(newPosition);
	penModel.object3D.position.x = newPosition.x;
	penModel.object3D.position.y = newPosition.y;
	penModel.object3D.position.z = newPosition.z;
	// console.log(penModel.object3D.position);
}

function RepositionOnResize() {
	aspectRatio = GetAspectRatio();
	if(isHome)
	{
		if(aspectRatio < (12/10))
		{
			SetPenPosition({x:0, y:-(1.5/aspectRatio), z:-(5/aspectRatio)})
		}
		else
		{
			SetPenPosition({x:0, y:-.5, z:0})
		}
	}
	else if (currentState == 4)
	{
		if(aspectRatio < (12/10))
		{
			camera.setAttribute('orbit-controls-kitmod', {
				enableRotate: true,
				rotateToSet: true,
				rotateTo: (farRadius + (8/aspectRatio)) + " " + phi + " " + theta,
			})
		}
		else {
			console.log("WideAspect: " + aspectRatio);
			camera.setAttribute('orbit-controls-kitmod', {
				enableRotate: true,
				rotateToSet: true,
				rotateTo: closeRadius + " " + phi + " " + theta,
			})
		}
	}
}

function TimerAnimation()
{
	timerCircle.set(0);
	timerCounter.style["-webkit-animation-play-state"] = 'running';
	timerCounter.style["animation-play-state"] = 'running';
	timerText.style["-webkit-animation-play-state"] = 'running';
	timerText.style["animation-play-state"] = 'running';
	timerCircle.animate(1, {
		duration: 5000,
		step: function() {
			timerCircle.text.innerHTML = Math.round(timerCircle.value() * 15);
		}
	}, function() {
		timerCounter.style["-webkit-animation-play-state"] = 'paused';
		timerCounter.style["animation-play-state"] = 'paused';
		timerText.style["-webkit-animation-play-state"] = 'paused';
		timerText.style["animation-play-state"] = 'paused';
		timerSetTimeout = setTimeout( function() {
			if(states[currentState].stepAnimations[states[currentState].stepProgress].timerAnim)
			{
				// console.log("Timer finished. Progressing...")
				ProgressState();
			}
		}, 100);
	});
}

function FadeOutElement(element, delay)
{
	var elOpacity = { val: 1 };
	var fadeElement = new TWEEN.Tween( elOpacity )
	.to({ 
		val: 0
	}, 600)
	.onUpdate(function() {
		element.style.opacity = elOpacity.val;
	})
	.delay(delay);
	fadeElement.start();
}

function SetArrow(hasArrow, opacity, speed)
{
	// console.log("Setting " + hasArrow + " to " + opacity);
	if(hasArrow == 'lockB')
	{
		if(opacity == 1)
		{
			setTimeout(function () {
				penModel.setAttribute('fade-mesh', {
					meshNameStartsWith: 'pcisePen_rigLock_Spin',
					targetOpacity: opacity,
					speed: speed
				});
			}, 500);
			setTimeout(function () {
				penModel.setAttribute('fade-mesh', {
					meshNameStartsWith: 'pcisePen_rigLock_Spin',
					targetOpacity: 0,
					speed: speed
				});
			}, 1200);
		}
	}
	if(hasArrow == 'capB')
	{
		if(opacity == 1)
		{
			setTimeout(function () {
				penModel.setAttribute('fade-mesh', {
					meshNameStartsWith: 'pcisePen_rigCap_Spin',
					targetOpacity: opacity,
					speed: speed
				});
			}, 500);
			setTimeout(function () {
				penModel.setAttribute('fade-mesh', {
					meshNameStartsWith: 'pcisePen_rigCap_Spin',
					targetOpacity: 0,
					speed: speed
				});
			}, 1200);
		}
	}
}

function DisableArrows()
{
	penModel.setAttribute('fade-mesh', {
		meshNameStartsWith: 'pcisePen_rigLock_Spin',
		targetOpacity: 0,
		speed: 50
	});
	penModel.setAttribute('fade-mesh', {
		meshNameStartsWith: 'pcisePen_rigCap_Spin',
		targetOpacity: 0,
		speed: 50
	});
}

function ExplodePen()
{
	expandToggle.classList.add('selected');
	exploded = true;
}

function CollapsePen()
{
	expandToggle.classList.remove('selected');
	exploded = false;
}

function ShowThigh()
{
	thighModel.setAttribute('visible', true);
	thighPosition = { 
		x: 0,
		y: -2,
		z: -2
	}
	var showThigh = new TWEEN.Tween( thighPosition )
	.to({ 
		x: 0, 
		y: 0.85, 
		z: -2
	}, 700)
	.easing( TWEEN.Easing.Cubic.InOut )
	.onUpdate(function() {
		thighModel.object3D.position.y = thighPosition.y;
	})
	showThigh.start();
	thighShown = true;
}

function HideThigh()
{
	thighPosition = { 
		x: 0,
		y: 0.85,
		z: -2
	}
	var hideThigh = new TWEEN.Tween( thighPosition )
	.to({ 
		x: 0, 
		y: -2, 
		z: -2
	}, 500)
	.easing( TWEEN.Easing.Cubic.InOut )
	.onUpdate(function() {
		thighModel.object3D.position.y = thighPosition.y;
	})
	.onComplete( function() {
		thighModel.setAttribute('visible', false);
	})
	hideThigh.start();
	thighShown = false;
}

function ThighInjectionAnimation()
{
	thighPosition = { 
		x: 0,
		y: 0.85,
		z: -2
	}
	var raiseThigh = new TWEEN.Tween( thighPosition )
	.to({ 
		x: 0, 
		y: 1, 
		z: -2
	}, 700)
	.easing( TWEEN.Easing.Cubic.InOut )
	.onUpdate(function() {
		thighModel.object3D.position.y = thighPosition.y;
	})
	raiseThigh.start();

	thighModel.removeAttribute('animation-mixer');
	thighModel.setAttribute('animation-mixer', {
		clip: 'Inject',
		loop: 'repeat',
		timeScale: 1,
		repetitions: 1,
		clampWhenFinished: true,
		crossFadeDuration: .4
	});
	// thighModel.addEventListener('animation-finished', function() {
	// 	// console.log('Callback triggered');
	// 	setTimeout(function()
	// 	{
	// 		thighPosition = { 
	// 			x: 0,
	// 			y: 1,
	// 			z: -2
	// 		}
	// 		var lowerThigh = new TWEEN.Tween( thighPosition )
	// 		.to({ 
	// 			x: 0, 
	// 			y: 0.85, 
	// 			z: -2
	// 		}, 700)
	// 		.easing( TWEEN.Easing.Cubic.InOut )
	// 		.onUpdate(function() {
	// 			thighModel.object3D.position.y = thighPosition.y;
	// 		})
	// 		lowerThigh.start();

	// 		thighModel.removeAttribute('animation-mixer');
	// 		thighModel.setAttribute('animation-mixer', {
	// 			clip: 'Lift',
	// 			loop: 'repeat',
	// 			timeScale: 1,
	// 			repetitions: 1,
	// 			clampWhenFinished: true,
	// 			crossFadeDuration: .4
	// 		});
	// 	}, 5500);
	// 	thighModel.removeEventListener('animation-finished', arguments.callee); 
	// });
}

function ShowPen()
{
	penModel.setAttribute('visible', true);
	penShown = true;
}

function HidePen()
{
	penModel.setAttribute('visible', false);
	penShown = false;
}

function GetAspectRatio()
{
	return window.innerWidth / window.innerHeight;
}

window.onload = function() { setTimeout(init(), 1000); };
function animate(time) {
	requestAnimationFrame(animate)
	TWEEN.update(time)
}
requestAnimationFrame(animate)