#pragma once

#include <fcntl.h>
#include <fmt/core.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>

#include <chrono>
#include <cinttypes>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <thread>
#include <vector>

#include "MqttClient.hpp"
#include "coreExcept.hpp"
#include "gpioPort.hpp"
#include "loRa.hpp"
#include "mutex.hpp"
#include "queue.hpp"
#include "semaphore.hpp"
#include "spiPort.hpp"
#include "textUtils.hpp"
#include "thread.hpp"

#include "palHw.hpp"

class LinMot {
   public:
    LinMot(OutputPort& o1, OutputPort& o2)
        : _out1(o1),
          _out2(o2) {
    }

    void moveOut() {
        _out2.write(false);
        _out1.write(true);
        _locked = true;
    }
    void moveIn() {
        _out2.write(true);
        _out1.write(false);
        _locked = false;
    }

    bool isLocked() {
        return _locked;
    }

   private:
    OutputPort& _out1;
    OutputPort& _out2;
    bool _locked;
};

class DeviceIoState {
   public:
    DeviceIoState(pal::InputTransAware& entry,
           pal::InputTransAware& end,
           pal::InputTransAware& pulled,
           LinMot& latch)
        : SwordEntry(entry),
          SwordEnd(end),
          SwordPulled(pulled),
          SwordLatch(latch) {
    }

    void tick() {
        SwordEntry.sample();
        SwordEnd.sample();
        SwordPulled.sample();
    }   
    
    pal::InputTransAware& SwordEntry;
    pal::InputTransAware& SwordEnd;
    pal::InputTransAware& SwordPulled;
    LinMot& SwordLatch;
};