#pragma once
#include "fs/VFS.h"
#include "fs/devices/SlavePTY.h"
#include <bits/termios.h>
#include <luna/Buffer.h>

class MasterPTY : public VFS::DeviceInode
{
  public:
    MasterPTY() = default;

    static Result<SharedPtr<VFS::Inode>> create_pair(int index);

    VFS::InodeType type() const override
    {
        return VFS::InodeType::CharacterDevice;
    }

    Result<u64> query_shared_memory(off_t, usize) override
    {
        return err(ENOTSUP);
    }

    VFS::FileSystem* fs() const override
    {
        return nullptr;
    }

    Result<usize> read(u8* buf, usize offset, usize length) const override;

    Result<usize> write(const u8* buf, usize offset, usize length) override;

    Result<u64> ioctl(int request, void* arg) override;

    Result<u64> isatty() const override
    {
        return 1;
    }

    Result<void> truncate(usize) override
    {
        // POSIX says truncate is for regular files, but doesn't tell us what error to return for non-regular files.
        return err(EINVAL);
    }

    bool will_block_if_read() const override
    {
        return m_buffer.is_empty();
    }

    void did_link() override
    {
        m_metadata.nlinks++;
    }

    void did_unlink() override
    {
        m_metadata.nlinks--;
    }

    virtual ~MasterPTY();

  private:
    struct termios m_settings;
    mutable Buffer m_buffer;
    SharedPtr<SlavePTY> m_slave;
    mutable Option<pid_t> m_foreground_process_group;
    struct winsize m_window;

    Result<void> handle_background_process_group(bool can_succeed, int signo) const;

    int m_index;

    friend class SlavePTY;
};