#ifndef __WOZSPECTOR_H
#define __WOZSPECTOR_H

#include "woz.h"
#include "vent.h"

class Wozspector : public Woz {
public:
  Wozspector(bool verbose, uint8_t dumpflags);
  virtual ~Wozspector();

  Vent *getTree();
  void displayTree();
  
  virtual void displayInfo() = 0;
  
  // getFileContents will will malloc(); caller must call free()
  // return value is the length
  virtual uint32_t getFileContents(Vent *e, char **toWhere) = 0;

  // Returns the approximate on-disk allocation size (in bytes) for the
  // given entry, from directory metadata alone. Used for warning about
  // logical-vs-allocated mismatches when copying files out.
  virtual uint32_t getAllocatedByteCount(Vent *e) = 0;

  // Returns the full allocated contents of the file by walking the on-disk
  // data sectors/blocks directly, ignoring any in-file length header. Used
  // by cpout -A to recover files whose catalog length is a small "stub"
  // that hides a larger payload. Default impl just delegates to
  // getFileContents for filesystems where header-length == allocation.
  virtual uint32_t getFileAllocation(Vent *e, char **toWhere) {
    return getFileContents(e, toWhere);
  }

  // Dos and ProDOS have different size applesoft headers, which affects listing
  virtual uint8_t applesoftHeaderBytes() = 0;

  virtual bool writeFileToImage(uint8_t *fileContents,
                                char *fileName,
                                uint8_t fileType, // ProDOS file type, always
                                uint16_t auxTypeData,
                                uint32_t fileSize) = 0;

  // Delete a file by name from the (root) directory, freeing its storage.
  // Every filesystem implements this.
  virtual bool removeFile(const char *fileName) = 0;

  // Delete an empty subdirectory by name. Only filesystems with
  // subdirectories (ProDOS) override this; the default reports that the
  // operation is unsupported and changes nothing.
  virtual bool removeDirectory(const char *dirName);

  // Install boot code into the volume's boot blocks (ProDOS: blocks 0-1).
  // The default reports that the operation is unsupported.
  virtual bool writeBootBlocks(const uint8_t block0[512],
                               const uint8_t block1[512]);

  // Rename the volume (ProDOS: the volume directory header in block 2).
  // Caller passes a pre-validated name. The default reports that the
  // operation is unsupported.
  virtual bool renameVolume(const char *newName);

  // Recursively delete a subdirectory and everything beneath it (contents
  // first, then the directory itself). Only filesystems with subdirectories
  // (ProDOS) override this; the default reports that the operation is
  // unsupported and changes nothing.
  virtual bool removeDirectoryRecursive(const char *dirName);

  // Create a new (empty) subdirectory by name. Only filesystems with
  // subdirectories (ProDOS) override this; the default reports that the
  // operation is unsupported and changes nothing.
  virtual bool makeDirectory(const char *dirName);

  // Resolve a name (ProDOS: a possibly slash-separated path) to its tree
  // entry, or NULL. The returned Vent is owned by the tree — do not free it.
  // The base implementation matches a flat leaf name; ProDOS overrides it to
  // walk subdirectory paths.
  virtual Vent *findEntry(const char *path);

  // List the contents of a subdirectory named by `path`. Only ProDOS has
  // subdirectories; the base implementation says so and lists nothing.
  virtual void displayDirectory(const char *path);

  virtual void inspectFile(const char *fileName, Vent *fp) = 0;

  // Returns true if the loaded image looks like the filesystem this
  // spector knows how to handle. Used at startup to warn when the user
  // invoked wozit with the wrong -d/-p mode.
  virtual bool probe() = 0;

protected:
  virtual Vent *createTree() = 0;
  virtual void displayTree(Vent *tree);
  virtual void freeTree(Vent *tree);
  
  void appendTree(Vent *a);

protected:
  Vent *tree;
};

#endif
