/* -*- c++ -*-
 * io.h: interface between the common component io.cpp and the
 * frontend-specific file-reading implementation
 */

enum class FileType { Uncached, File, Stdin, Fd };
enum class SpecialSetup { TermModes };

class FileReaderRaw {
    enum { Open, CleanedUp, Closed } state;
  protected:
    virtual void cleanup_inner() {}
    virtual void close_inner() {}
    virtual size_t read_inner(void *, size_t) = 0;
    virtual void setup_inner(SpecialSetup) {}
  public:

    FileReaderRaw();
    virtual ~FileReaderRaw();
    void cleanup();
    void close();
    size_t read(void *buf, size_t size);
    void setup(SpecialSetup);
};

struct BufferingReaderCacheKey {
    FileType type;
    string id;
    BufferingReaderCacheKey(FileType type_, string id_);
    explicit BufferingReaderCacheKey(FileType type_);
    bool operator<(const BufferingReaderCacheKey &rhs) const;
};

class FileOpener {
  public:
    virtual ~FileOpener() = default;
    virtual BufferingReaderCacheKey key() const = 0;
    virtual string name() const = 0;
    virtual unique_ptr<FileReaderRaw> open() const = 0;
};

class FileAccessContext {
  public:
    virtual ~FileAccessContext() = default;
    virtual unique_ptr<FileOpener> file_opener(const string &filename) = 0;
    virtual unique_ptr<FileOpener> fd_opener(int fd) = 0;
    virtual unique_ptr<FileOpener> stdin_opener() = 0;
};

unique_ptr<FileAccessContext> make_cli_file_access_context();

void io_cleanup();
void io_setup(SpecialSetup sstype);

Spigot spigot_basefile(FileAccessContext &fac,
                       int base, const char *filename, bool exact);
Spigot spigot_cfracfile(FileAccessContext &fac,
                        const char *filename, bool exact);
Spigot spigot_basefd(FileAccessContext &fac, int base, int fd);
Spigot spigot_cfracfd(FileAccessContext &fac, int fd);
Spigot spigot_basestdin(FileAccessContext &fac, int base);
Spigot spigot_cfracstdin(FileAccessContext &fac);
