
if(process.platform !== 'darwin') var gpio = require('rpi-gpio');

const player = require('node-wav-player');

// ist an wenn im kind mode (erw LED is aus)
const childLED = 37;
// ist and wenn im erwachsenen Mode (kind LED ist aus)
const erwLED = 38;
// status : ist an wenn in ruhe position, blinkt, wenn gestartet, ist aus bei fail
const statusLED = 40;
// setze auf HIGH wenn fail (klingel relais)
const failSwitch = 35;

// warte auf spielstart wenn auf HIGH
const startButton = 32;
// beende spiel wenn auf HIGH
const finishButton = 31;
// faile spiel wenn auf HIGH
const failButton = 29;
// wechsle kind/erwachen Modus + LED
const toggleButton = 33;

// wird je nach modus gesetzt und abgespielt wenn start
const backgroundGrown = "jeopardy.wav";
const backgroundChild = "northsouth.wav";
// wird zufallig zu zufaelligen momenten abgespielt (erw mode)
const erschreckSounds = [ "ziege.wav", "scream.wav", "lough.wav" ];
// wird nach fester zeit + random oder spaeter nach der besten zeit abgespielt (erw mode)
const stresserSound  = "sharks.wav";
// wird bei fail abgespielt (zonk) 
const failSound = "zonk.wav";
// hurra wird bei finish abgespielt
const finishSound = "kidscheering.wav";

const GROWN=1;
const CHILD=2;

const STATES = {
    STARTED: 'started',
    FINISH: 'finshed',
    FAIL: 'failed'
};

const bounce = {};

var STATE = STATES.FINISH;
var MODE = GROWN;
var GAME = {};

function setup() {
    console.log('Setting up GPIOs');

    if(process.platform === 'darwin') {
	setTimeout(start, 500);
	setTimeout(fail, 3500);
	setTimeout(start, 4000);
	setTimeout(finish, 9000);
	setTimeout(fail, 10000);
	setTimeout(finish, 11000);
	return;
    }
    gpio.setup(failSwitch, gpio.OUT, () => {
        gpio.output(failSwitch, false);
    });
    gpio.setup(statusLED, gpio.OUT, () => {
        gpio.output(statusLED, true);
    });
    gpio.setup(childLED, gpio.OUT, () => {
        gpio.output(childLED, true);
    });
    gpio.setup(erwLED, gpio.OUT, () => {
        gpio.output(erwLED, false);
    });

    gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_RISING);
    gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_RISING);
    gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_RISING);
    gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_RISING);

    gpio.on('change', (channel, value) => {
	if(bounce[channel] === true) return;
	console.log('Change',channel, value);
	bounce[channel] = true;
        setTimeout(() => { bounce[channel] = false; console.log('Debounced', channel); }, 500);
        switch(channel) { 
            case startButton:
                start(value);
                break;
            case finishButton:
                finish(value);
                break;
            case failButton:
                fail(value);
                break;
            case toggleButton:
                toggle(value);
                break;
            default:
                console.log('Alert! Unknown button change',channel);
        }
    });
    console.log('Done. Game logic started. Waiting for input');
}

function gameTimer() {
    console.log('game timer called');
    GAME.events.forEach((el) => {
        if(el.start === GAME.runTime) {
            console.log('Event :', el);
	    playSound(el.sound);
	}
    });
    GAME.runTime++;
}

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function start(value) {
    GAME = {
        events: [],
        runTime: 0
    };
    if(STATE === STATES.FINISH || STATE === STATES.FAIL) {
        STATE = STATES.STARTED;
        // set all params for next game, then start counter and event timer
        if(MODE === GROWN) {
            GAME.events.push({ sound: backgroundGrown, start: 0});
            GAME.events.push({ sound: stresserSound, start: 30+getRandomInt(10) });
            GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: getRandomInt(10) });
            GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10) });
            GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 20+getRandomInt(10) });
            GAME.mode = GROWN;
            GAME.fail = failSound;
            GAME.finish = finishSound;
            GAME.runtime = 0;
        }
        if(MODE === CHILD) {
            GAME.events.push({ sound: backgroundChild, start: 0});
            GAME.events.push({ sound: stresserSound, start: 40+getRandomInt(10)});
            GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10)});
            GAME.mode = CHILD;
            GAME.fail = failSound;
            GAME.finish = finishSound;
            GAME.runtime = 0;
        }
    	console.log('Starting new game', JSON.stringify(GAME, 2, null));
	console.log(GAME);
        GAME.countTimer = setInterval(gameTimer, 1000);
    } else {
        console.log('START not in state', STATE);
    }
}

function finish(value) {
    console.log('Finish');
    if(STATE === STATES.STARTED) {
        console.log('You made it in', GAME.runTime, 'seconds');
	playSound(GAME.finish);
        STATE = STATES.FINISH;
	clearInterval(GAME.countTimer)
	GAME.events = [];
    } else {
        console.log('FINISH not in state', STATE);
    }
}

function fail(value) {
    console.log('Fail');
    if(STATE === STATES.STARTED) {
        console.log('You failed after', GAME.runTime, 'seconds');
	playSound(GAME.fail);
        STATE = STATES.FAIL;
	clearInterval(GAME.countTimer)
        GAME.events = [];
    } else {
        console.log('FAIL not in state', STATE);
    }
}

function toggle(value) {
    if(STATE === STATES.FINISH || STATE === STATES.FAIL) {
        console.log('Toggle');
        if(MODE === CHILD) { 
            MODE = GROWN;
	    // set all values for GROWN mode
        }
        if(MODE === GROWN) {
            MODE = CHILD;
	    // set all values for CHILD mode
        }
    } else {
        console.log('Toggle not in state', STATE);
    }
}

function playSound(file){
    console.log("Play sound : ", file);
    if(GAME.playing) {
       console.log("Stopping old soundfile", GAME.playing);
       player.stop();
    }
    GAME.playing = file;
    player.play({ path: `wav/${file}`, sync: true }).then(() => { delete GAME.playing })
}

setup();
