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

#ifndef PUSHBUTTON2_TESTSWITCH
#define PUSHBUTTON2_TESTSWITCH

#include "Common.h"
#include <SwitchExtensions.h>

void doPushButton2Tests(int id){  // ID_PUSHBUTTONTEST2 = 4
  // longStartMillis, repeatMillis
  PushButtonRepeatAnalyzer TestPBRAnalyzer(10, 5);
  TestSwitch stdSwitch(&TestPBRAnalyzer, true, INPUT_PIN, 0, true);
  unsigned long tmpMicros, startmicro = 0;
  int seq;
  boolean tmpBool;

  stdSwitch.setMapping(PBR_STATE_E_OFF, 10);
  stdSwitch.setMapping(PBR_STATE_E_SINGLE, 11);
  stdSwitch.setMapping(PBR_STATE_E_CONT_A, 12);
  stdSwitch.setMapping(PBR_STATE_E_CONT_B, 13);

  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);

  seq = 10; // 1. change -> state OFF
  stdSwitch.setRawState(1); // invertRaw -> 0
  check(stdSwitch.getState(),SW_STATE_UNDEFINED,id,seq+1);
  check(stdSwitch.hasChanged(),true,id,seq+2);
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+3);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+4);
  check(stdSwitch.hasChanged(),false,id,seq+5);
  check(stdSwitch.getMappedState(),10,id,seq+6);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+7);

  seq = 20; // 2. change -> start single push 
  stdSwitch.setRawState(0); // invertRaw -> 1
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+1);
  check(stdSwitch.hasChanged(),false,id,seq+2);
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+3);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+4);
  check(stdSwitch.hasChanged(),false,id,seq+5);
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+8);
  check(stdSwitch.getMappedState(),10,id,seq+6);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+7);

  seq = 30; // 3. change -> end single push 
  stdSwitch.setRawState(1); // invertRaw -> 0
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+5);
  delay(5); // wait shorter than long push
  check(stdSwitch.hasChanged(),true,id,seq+6);  //SINGLE
  check(stdSwitch.getState(),PBR_STATE_E_SINGLE,id,seq+7);
  check(stdSwitch.getPrevState(),PBR_STATE_E_OFF,id,seq+8);
  check(stdSwitch.getMappedState(),11,id,seq+10);
  check(stdSwitch.getPrevMappedState(),10,id,seq+11);

  seq = 40; // 4. change -> off 
  check(stdSwitch.hasChanged(),true,id,seq+1);  // OFF
  check(stdSwitch.getState(),PBR_STATE_E_OFF,id,seq+2);
  check(stdSwitch.getPrevState(),PBR_STATE_E_SINGLE,id,seq+3);
  check(stdSwitch.getMappedState(),10,id,seq+4);
  check(stdSwitch.getPrevMappedState(),11,id,seq+5);

  // test repeating long push
  stdSwitch.setReadCycleMillis(0);
  stdSwitch.setDebounceMillis(0);
  stdSwitch.setInvertRaw(false); // switch to positive logic
  stdSwitch.reset();

  seq = 50; // 1. change 
  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(),PBDL_STATE_E_OFF,id,seq+6);
  check(stdSwitch.getPrevState(),SW_STATE_UNDEFINED,id,seq+7);
  check(stdSwitch.getMappedState(),10,id,seq+8);
  check(stdSwitch.getPrevMappedState(),SW_STATE_UNDEFINED,id,seq+9);

  seq = 60; // 2. change -> start long push with repeated changes
  stdSwitch.setRawState(1); 
  check(stdSwitch.hasChanged(),false,id,seq+1);
  check(stdSwitch.getState(),PBDL_STATE_E_OFF,id,seq+2);
  delayMicroseconds(8000);
  check(stdSwitch.hasChanged(),false,id,seq+3);
  check(stdSwitch.getState(),PBDL_STATE_E_OFF,id,seq+4);
  delayMicroseconds(4000); // 12ms
  check(stdSwitch.hasChanged(),true,id,seq+5);
  check(stdSwitch.getState(),PBR_STATE_E_CONT_A,id,seq+6);
  delayMicroseconds(1000); // 13ms
  check(stdSwitch.hasChanged(),false,id,seq+7);
  check(stdSwitch.getState(),PBR_STATE_E_CONT_A,id,seq+8);
  delayMicroseconds(4000); // 17ms
  check(stdSwitch.hasChanged(),true,id,seq+9);
  check(stdSwitch.getState(),PBR_STATE_E_CONT_B,id,seq+10);
  delayMicroseconds(1000); // 18ms
  check(stdSwitch.hasChanged(),false,id,seq+11);
  check(stdSwitch.getState(),PBR_STATE_E_CONT_B,id,seq+12);
  delayMicroseconds(4000); // 22ms
  check(stdSwitch.hasChanged(),true,id,seq+13);
  check(stdSwitch.getState(),PBR_STATE_E_CONT_A,id,seq+14);
  stdSwitch.setRawState(0);
  check(stdSwitch.hasChanged(),true,id,seq+15);
  check(stdSwitch.getState(),PBDL_STATE_E_OFF,id,seq+16);

  // performance

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

  Serial.print("1000 * hasChanged() true: ");

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

  startmicro = micros();
  for(int i = 0 ; i < 1000 ; i++){
    stdSwitch.setRawState(i & 0x0001);
    tmpBool = stdSwitch.hasChanged();
  }
  Serial.print(micros() - startmicro);
  Serial.println(" micros");

  Serial.print("1000 * hasChanged() false: ");

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

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

#endif
