/*
  Logger - High level handling of file storage of logger data.
  Created by Jan Benda, August 28th, 2024.
*/

#ifndef Logger_h
#define Logger_h

#include <TimeLib.h>
#include <Snooze.h>
#include <Input.h>
#include <SDCard.h>
#include <SDWriter.h>
#include <RTClock.h>
#include <Blink.h>
#include <MicroConfig.h>


class Logger {
  
public:

  Logger(Input &aiinput, SDCard &sdcard,
	 RTClock &rtclock, Blink &blink);
  Logger(Input &aiinput, SDCard &sdcard,
	 RTClock &rtclock, Blink &blink,
	 Blink &errorblink, Blink &syncblink);
  Logger(Input &aiinput, SDCard &sdcard0, SDCard &sdcard1,
	 RTClock &rtclock, Blink &blink);

  // Halt with error message and blinking.
  void halt(int errorcode=0, Stream &stream=Serial);

  // Check accessibility of SD cards.
  // Run menu and halt if the main SD card can not be written.
  // If check_backup force checking backup SD card as well.
  bool check(Config &config, bool check_backup=false);

  // If secondary SD card is not available, end its usage.
  void endBackup(SPIClass *spi=NULL);

  // Check availability of SD card, set real-time clock from file,
  // load configuration file, execute menu, and report on serial.
  void configure(Config &config);

  // Hibernate until start_time is reached.
  void snooze(const char *start_time);

  // Reduce CPU speed according to sampling rate.
  void setCPUSpeed(uint32_t rate);

  // Report blink pins.
  void reportBlink(Stream &stream=Serial) const;

  // Initialze, check and start analog input.
  void startInput(uint8_t nchannels=0);
  
  // Initialize recording directory and file metadata.
  void setup(const char *path, const char *filename,
	     const char *software, bool randomblinks=false,
	     float blinktimeout=0.0, float synctimeout=0.0);

  // Delay with double blinks for initial_delay seconds.
  // Initialize a potential stop time.
  void initialDelay(float initial_delay, const char *stop_time=0,
		    Stream &stream=Serial);

  // Open files.
  void start(float filetime);
  
  // Open files and write metadata from config.
  void start(float filetime, Config &config);
  
  // Open files and write metadata from config.
  // Add more metadata to amplifier.
  void start(float filetime, Config &config, Menu &amplifier);

  // Close files.
  void close();

  // Call this in loop() for writing data to files.
  void update();

  // True, if data are stored in files.
  bool saving() const { return Saving; };

  String baseName() const { return File0.baseName(); };

  void R41powerDownCAN();
  

protected:
  
  // Generate file name, open main file and write first chunk of data.
  void open(bool backup);

  // Write all metadata into file.
  void writeMetadata(Config &config);
  
  // Open file that stores blink times.
  void openBlinkFiles();
  
  // Store blink times in files.
  void storeBlinks();
  
  // Close blink files.
  void closeBlinks();

  // Write recorded data to files.
  bool store(SDWriter &sdfile, bool backup);

  // Close all files and reboot.
  virtual void stop();  

  // Derived classes can insert code here before the next file is opened.
  virtual bool synchronize() { return false; };

  Input &AIInput;
  SDCard *SDCard0;
  SDCard *SDCard1;
  SDWriter File0;
  SDWriter File1;
  RTClock &Clock;
  Blink NoBlink;
  Blink &StatusLED;
  Blink &ErrorLED;
  Blink &SyncLED;
  
  bool RandomBlinks;
  FsFile BlinkFile0;
  FsFile BlinkFile1;
  unsigned long BlinkTimeout;
  unsigned long SyncTimeout;
  
  String Filename;       // Template for filename
  String PrevFilename;   // Previous file name
  bool Saving;
  int FileCounter;
  int Restarts;
  int NextStore;
  int NextOpen;
  
  time_t StartTime;
  time_t StopTime;
  SnoozeAlarm Alarm;
  SnoozeSPI SnoozeSDCard;
  SnoozeBlock SnoozeConfig;
  
};


#endif

