//***********************************************************************
// Test.h   - contains test functions for SINKER Camera Controller (SCC)
//***********************************************************************
#ifndef TEST_H
#define TEST_H

#include "Utils.h"
#include "Config.h"
#include "Test.h"
#include "SystemControl.h"
#include "Sensors.h"
#include "SystemTrigger.h"
#include "SystemConfig.h"

class SCCTest {

public:
    SCCTest() {}
   ~SCCTest() {}

    bool test_interactively() {
        bool result = false;
        while(true) {
            bool with_prompts = confirm(&DEBUGPORT, "Type 'y' within 5 seconds to run tests...", 5000);
            if (with_prompts) {
                result = test_all(with_prompts);
            } else {
                break;
            }
        }
        DEBUGPORT.println("\nExecuting app...");
        return result;
    }

    bool test_all(bool with_prompts=false) {
        bool pass = true;
        pass = pass && test_gpio(with_prompts);
        pass = pass && test_led(with_prompts);
        pass = pass && test_strobe(with_prompts);
        pass = pass && test_bme(with_prompts);
        pass = pass && test_vref(with_prompts);
        return pass;
    }

    bool test_vref(bool with_prompts=false) {
        if (with_prompts && !confirm(&DEBUGPORT, "Test Vref? [y/n]: ", 10000)) {
            return true;
        }
        analogReadResolution(10);
        float vref = analogRead(SCC_VREF)/1024.0*3.3;
        DEBUGPORT.print("\nLooking for 2.5 V...analog Vref is: ");
        DEBUGPORT.println(vref);
        return true;
    }

    bool test_led(bool with_prompts=false) {
        if (with_prompts && !confirm(&DEBUGPORT, "Test LED? [y/n]: ", 10000)) {
            return true;
        }
        for (int i = 0; i < 5; i++) {
            Blink(500);
        }
        return true;
    }

    bool test_strobe(bool with_prompts=false) {
        if (with_prompts && !confirm(&DEBUGPORT, "Test Strobe? [y/n]: ", 10000)) {
            return true;
        }
        // Are strobes charged?
        pinMode(SCC_PA02, INPUT);
        if (digitalRead(SCC_PA02) == LOW) {
            if (with_prompts && !confirm(&DEBUGPORT, "Strobes are not charged. Continue? [y/n]: ", 10000)) {
                return false;
            }
        }
        Blink(50, 2);
        // Create a low to high edge on SCC_PA10
        pinMode(SCC_PA10, OUTPUT);
        digitalWrite(SCC_PA10, LOW);
        delayMicroseconds(5);
        digitalWrite(SCC_PA10, HIGH);
        // 5 us later, Fire strobes
        delayMicroseconds(5);
        pinMode(SCC_PB02, OUTPUT);
        digitalWrite(SCC_PB02, HIGH);
        delayMicroseconds(5);
        digitalWrite(SCC_PB02, LOW);
        digitalWrite(SCC_PA10, LOW);
        Blink(1000, 1);
        return true;
    }

    bool test_bme(bool with_prompts=false) {
        if (with_prompts && !confirm(&DEBUGPORT, "Test Env? [y/n]: ", 10000)) {
            return true;
        }

        bool result = false;
        // sys.bmeSwitch(ON);
        delay(2000);
        if (!_bme.begin(0x77)) {
            DEBUGPORT.println("\nBad BME280 status...");
            Blink(100, 2);
            result = false;
        } else {
            DEBUGPORT.println("\nGood BME280 status...");
            Blink(100, 10);
            result = true;
        }
        //sys.bmeSwitch(OFF);
        return result;
    }

    bool test_gpio(bool with_prompts=false) {
        if (!confirm(&DEBUGPORT, "Test GPIO? [y/n]: ", 10000)) {
            return true;
        }
        int gpioset[] = {SCC_PA02, SCC_PA03, SCC_PA10, SCC_PA11,
                         SCC_PA18, SCC_PA19, SCC_PA20, SCC_PA21,
                         SCC_PB02, SCC_PB03, SCC_PB22, SCC_PB23};
        // First apply pullup to each pin in the gpio set
        int npins = sizeof(gpioset)/sizeof(gpioset[0]);
        for (int i = 0; i < npins; i++) {
            pinMode(gpioset[i], INPUT_PULLUP);
            Blink(100);
        }
        // Now continuously set each pin in each set to zero for 0.5s
        DEBUGPORT.println("Hit any key to stop cycling pins...");
        for (int i = 0; !DEBUGPORT.available(); i++) {
            char pinbuf[20];
            snprintf(pinbuf, 19, "%d", gpioset[i%npins]);
            DEBUGPORT.println(pinbuf);
            digitalWrite(gpioset[i%npins], LOW);
            Blink(250);
            digitalWrite(gpioset[i%npins], HIGH);
        }
        // Consume the character entered by the user
        DEBUGPORT.read();
            return true;
        }

protected:
};

#endif