// This script contains functionality to trigger any available switches as set up in the global Map table.

this.Name = "UseSwitch_PT";
this.Parent = "LowLevel";		// PathThrough states must be low level or they will not be used.

this.OnPathThrough = function(data)
{
	if (this.IsActive())
		{ return; }

	if (Map.Switches) {
		currentswitch = Map.Switches[data];
		if(currentswitch) {
			if(currentswitch.Enabled) {
				this.CurrentSwitch = currentswitch;
				return true; // script will activate
			}
		}
		else {
			Util.ScriptDebugPrint("PathThrough UseSwitch", "disabled", data + " not found in Map.Switches");
		}
	} else {
		Util.ScriptDebugPrint("PathThrough UseSwitch", "disabled", ", Map.Switches does not exist");
	}
	return false;  // script will not activate
};

this.Update = function()
{
	pathSuccess = false;
	currentswitch = this.CurrentSwitch;

	if( !currentswitch.Waypoint) {
		Util.UpdateSwitchData();
	}

	if( !currentswitch.Timeout ) {
		currentswitch.Timeout = 2000;
	}

	if ( currentswitch.UseAsync ) {
		if ( !currentswitch.AsyncTimeout ) {
			currentswitch.AsyncTimeout = 5000;
		}
		counter = 0;
		while( currentswitch.Enabled && counter <= currentswitch.AsyncTimeout ) {
			this.GotoAsync(currentswitch.Waypoint.position, currentswitch.Waypoint.radius);
			// cs: distance calculation is 3d, so dont use waypoint radius
			if ( DistanceBetween(this.Bot.GetPosition() + Vector3(0,0,-32), currentswitch.Waypoint.position) <= 48.0f ) {
				pathSuccess = true;
				break;
			}
			else if ( this.Bot.GetVelocity().IsZero() ) { // large waypoint radius
				this.Bot.MoveTowards(currentswitch.Waypoint.position);
			}
			yield();
			counter += 20;
		}
	}
	else if ( this.Goto(currentswitch.Waypoint.position, currentswitch.Waypoint.radius) == EVENT.PATH_SUCCESS ) {
		pathSuccess = true;
	}

	if( pathSuccess ) {
		if ( !currentswitch.AimPosition ) {
			this.AddAimRequest(Priority.High, "facing", currentswitch.Waypoint.facing);
		}
		else {
			this.AddAimRequest(Priority.High, "position", currentswitch.AimPosition);
		}

		counter = 0;
		exitCondition = false;
		while( !exitCondition && currentswitch.Enabled && counter < currentswitch.Timeout ) {
			counter += 250;
			this.Bot.MoveTowards(currentswitch.Waypoint.position);
			this.Bot.PressButton( BTN.USE);

			sleep(0.25);

			if ( currentswitch.ExitConditions ) {
				foreach ( func in currentswitch.ExitConditions ) {
					if ( func(this.Bot) == true ) {
						if ( currentswitch.Debug )
							{ print(this.Bot.Name, "^2exit condition met for", currentswitch.WaypointName); }

						exitCondition = true;
						break;
					}
				}
			}
		}

		this.ReleaseAimRequest();

		//cs: wait function now overrides exitConditions
		if ( currentswitch.Wait && counter < currentswitch.Timeout) {
			while ( currentswitch.Wait() != true ) {
				//this.Goto can't be used inside moving elevators
				this.Bot.MoveTowards(this.Bot.GetPosition());
				yield();
			}
		}
	}
	else {
		this.BlackboardDelay(30, currentswitch.Serial);
	}

	 // Finish the state.
	this.Finished();
};
