/*
  Copyright (c) 2025-2026 Kay Kasper
  under the MIT License (MIT)
*/

#ifndef SWITCH_TESTSWITCH
#define SWITCH_TESTSWITCH

#include "Common.h"

void doSwitchTests(int id){  // ID_SWITCHTEST = 1
  TestSwitch stdSwitch(2, 0, INPUT_PIN, 0, 0, true);
  unsigned long tmpMicros, startmicro = 0;
  int seq;

  seq = 0; // no waits, negative logic
  stdSwitch.setReadCycleMillis(0);
  stdSwitch.setDebounceMillis(0);
  stdSwitch.setInvertRaw(true);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);

  stdSwitch.setRawState(1); // invertRaw -> 0
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+5);
  check(stdSwitch.hasChanged(),true,id,seq+6);
  check(stdSwitch.getState(),0,id,seq+7);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+8);
  check(stdSwitch.hasChanged(),false,id,seq+9);
  check(stdSwitch.getMappedState(),0,id,seq+10);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+11);

  stdSwitch.setRawState(0); // invertRaw -> 1
  check(stdSwitch.getState(),0,id,seq+12);
  check(stdSwitch.hasChanged(),true,id,seq+13);
  check(stdSwitch.getState(),1,id,seq+14);
  check(stdSwitch.getPrevState(),0,id,seq+15);
  check(stdSwitch.hasChanged(),false,id,seq+16);
  check(stdSwitch.getMappedState(),1,id,seq+17);
  check(stdSwitch.getPrevMappedState(),0,id,seq+18);

  seq = 20; // no waits, positive logic
  stdSwitch.setReadCycleMillis(0);
  stdSwitch.setDebounceMillis(0);
  stdSwitch.setInvertRaw(false);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);

  stdSwitch.setRawState(1);
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+5);
  check(stdSwitch.hasChanged(),true,id,seq+6);
  check(stdSwitch.getState(),1,id,seq+7);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+8);
  check(stdSwitch.hasChanged(),false,id,seq+9);
  check(stdSwitch.getMappedState(),1,id,seq+10);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+11);

  stdSwitch.setRawState(0);
  check(stdSwitch.getState(),1,id,seq+12);
  check(stdSwitch.hasChanged(),true,id,seq+13);
  check(stdSwitch.getState(),0,id,seq+14);
  check(stdSwitch.getPrevState(),1,id,seq+15);
  check(stdSwitch.hasChanged(),false,id,seq+16);
  check(stdSwitch.getMappedState(),0,id,seq+17);
  check(stdSwitch.getPrevMappedState(),1,id,seq+18);

  seq = 40; // readCycleMillis
  stdSwitch.setReadCycleMillis(2);
  stdSwitch.setDebounceMillis(0);
  stdSwitch.setInvertRaw(false);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);
  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),true,id,seq+5);
  check(stdSwitch.getState(),0,id,seq+6);
  stdSwitch.setRawState(1);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),0,id,seq+7);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),1,id,seq+8);
  check(tmpMicros >= 2000,true,id,seq+9);
  check(tmpMicros < 2100,true,id,seq+10);

  seq = 60; // debounceMillis
  stdSwitch.setReadCycleMillis(0);
  stdSwitch.setDebounceMillis(255);
  stdSwitch.setInvertRaw(false);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);
  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),true,id,seq+5);
  check(stdSwitch.getState(),0,id,seq+6);
  stdSwitch.setRawState(1);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),0,id,seq+7);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),1,id,seq+8);
  check(tmpMicros >= 260000,true,id,seq+9);
  check(tmpMicros < 265000,true,id,seq+10);

  seq = 80; // readCycleMillis + debounceMillis, readCycleMillis > debounceMillis
  stdSwitch.setReadCycleMillis(5);
  stdSwitch.setDebounceMillis(2);
  stdSwitch.setInvertRaw(false);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);
  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),true,id,seq+5);
  check(stdSwitch.getState(),0,id,seq+6);
  stdSwitch.setRawState(1);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),0,id,seq+7);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),1,id,seq+8);
  check(tmpMicros >= 7100,true,id,seq+9);
  check(tmpMicros < 7300,true,id,seq+10);

  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),false,id,seq+11);
  check(stdSwitch.getState(),1,id,seq+12);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),1,id,seq+13);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),0,id,seq+14);
  check(tmpMicros >= 7100,true,id,seq+15);
  check(tmpMicros < 7300,true,id,seq+16);

  seq = 100; // readCycleMillis + debounceMillis, readCycleMillis < debounceMillis
  stdSwitch.setReadCycleMillis(2);
  stdSwitch.setDebounceMillis(5);
  stdSwitch.setInvertRaw(false);
  stdSwitch.reset();
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+2);
  check(stdSwitch.getMappedState(),SW_STATE_UNDEFINED,id,seq+3);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+4);
  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),true,id,seq+5);
  check(stdSwitch.getState(),0,id,seq+6);
  stdSwitch.setRawState(1);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),0,id,seq+7);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),1,id,seq+8);
  check(tmpMicros >= 7100,true,id,seq+9);
  check(tmpMicros < 7300,true,id,seq+10);

  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),false,id,seq+11);
  check(stdSwitch.getState(),1,id,seq+12);
  startmicro = micros();
  while(!stdSwitch.hasChanged()){
    check(stdSwitch.getState(),1,id,seq+13);
  }
  tmpMicros = micros()-startmicro;
  check(stdSwitch.getState(),0,id,seq+14);
  check(tmpMicros >= 7100,true,id,seq+15);
  check(tmpMicros < 7300,true,id,seq+16);

  // performance

  Serial.println("\nPerformance Standard:");

  stdSwitch.setInvertRaw(false);
  stdSwitch.setReadCycleMillis(0);
  stdSwitch.setDebounceMillis(0);
  stdSwitch.reset();

  Serial.print("1000 * hasChanged() true: ");
  startmicro = micros();
  for(int i = 0 ; i < 1000 ; i++){
    stdSwitch.setRawState(i & 0x0001);
    if(!stdSwitch.hasChanged()) break; 
  }
  Serial.print(micros() - startmicro);
  Serial.println(" micros");

  Serial.print("1000 * hasChanged() false: ");
  startmicro = micros();
  stdSwitch.setRawState(0);
  stdSwitch.hasChanged();
  for(int i = 0 ; i < 1000 ; i++){
    stdSwitch.setRawState(0);
    if(stdSwitch.hasChanged()) break;
  }
  Serial.print(micros() - startmicro);
  Serial.println(" micros");
}

#endif
