let StateButton = require('../assets/StateButton');
const CLIENT = require('../javascripts/communication');
const DYNAMIC_LOADING = require('../javascripts/dynamicloading');
let STATES = [];
/**
* Class reperesenting a state on the state machine
*/
class State {
/**
* Creates a state
* @param {String} shortName code name for the state, no spaces
* @param {String} displayName Display name for the buttons and console logs, any format
* @param {Button} btn (Optional) Button to assign to state if button is already made,
* if creating a button assign null
* @param {String} btnColor Color to create state button
* @param {Boolean} ishazardous If the state requires confirmation to transition to
* @param {Boolean} isFault If the state is a fault state
*/
constructor(shortName, displayName, btn, btnColor, ishazardous, isFault) {
this.shortname = shortName;
this.displayName = displayName;
this.ishazardous = ishazardous;
this.idNum = STATES.length;
this.isFault = isFault;
if (btn) {
this.btn = btn;
} else {
this.btn = new StateButton(shortName, displayName, null, btnColor, ishazardous, this);
}
this.active = false;
STATES.push(this);
}
/**
* Either prompts the user to confirm activation or sets active state
* @param {HTMLElement} modalTemplate The template of the modal to display
*/
activate(modalTemplate, fromPod) {
if (this.ishazardous && !fromPod) {
this.confirmActive(modalTemplate);
} else {
this.setActive();
}
}
/**
* Sets the state as the active state
*/
setActive() {
this.active = true;
STATES.forEach((state) => {
state.setInactive();
});
this.active = true;
this.btn.activate();
CLIENT.sendOverride(this.shortName);
if (!this.isFault) {
DYNAMIC_LOADING.fillAllBounds(this.shortname);
}
}
/**
* Sets the state as an inactive state
*/
setInactive() {
this.active = false;
this.btn.deactivate();
}
/**
* Displays a confirmation window before transitioning to state
* @param {HTMLElement} modalTemplate The template of the modal to display
* @override
*/
confirmActive(modalTemplate) {
let modal = modalTemplate.cloneNode(true);
document.body.appendChild(modal);
State.toggleConfirmationModal(modal);
let button = modal.childNodes[1].childNodes[7];
let text = modal.childNodes[1].childNodes[5];
let closeButton = modal.childNodes[1].childNodes[1];
closeButton.addEventListener('click', () => {
modal.classList.toggle('show-modal');
document.body.removeChild(modal);
});
button.addEventListener('click', () => { State.toggleConfirmationModal(modal); });
text.innerHTML = `Are you sure you want to transition to ${this.displayName}?`;
let state = this;
button.addEventListener('click', () => {
state.setActive();
modal.classList.toggle('show-modal');
document.body.removeChild(modal);
});
}
/**
* Toggles showing/hiding a modal
* @param {HTMLElement} modal The modal to toggle
*/
static toggleConfirmationModal(modal) {
modal.classList.toggle('show-modal');
}
/**
* Returns the active state
* @returns {State} The active state or -1 if there is no active state
*/
static getActiveState() {
for (let i = 0; i < STATES.length; i++) {
if (STATES[i].active) {
return STATES[i];
}
}
return -1;
}
/**
* Sets the active state there should always be one active state
* @param {State} state State to set active, either State or idNumber
* @param {HTMLElement} modal The confirmation Modal
* @param {Boolean} fromPod If the command is from a pod packet (no confirmation needed)
*/
static setActiveState(state, modal, fromPod) {
if (typeof state === 'object') {
state.activate(modal, fromPod);
}
if (typeof state === 'number') {
STATES[state].activate(modal, fromPod);
}
}
/**
* Finds the state given the IDNumber
* @param {Number} id ID of state
* @returns {State} the state with specified id
*/
static getStateById(id) {
return STATES.find(state => state.idNum === id);
}
}
module.exports = State;