#include <windows.h>

namespace DatExportApiPrivate {
  typedef int (__stdcall * OpenDatFileFunc)(
                                        int, // handle
                                        const char*, // filename
                                        unsigned int, // flags
                                        int*, // did_master_map
                                        int*, // block_size
                                        int*, // vnum_dat_file
                                        int*, // vnum_game_data
                                        unsigned long*, // dat_file_id
                                        void*, // dat_id_stamp
                                        void* // first_iter_guid
                                        );

  typedef int (__stdcall * GetNumSubfilesFunc)(
                                        int // handle
                                        );

  typedef int (__stdcall * GetSubFileSizesFunc)(
                                        int, // handle
                                        int*, // file_id list pointer
                                        int*, // size list pointer
                                        int*, // iteration list pointer
                                        int, // offset (index from 0 to num_subfiles - 1)
                                        int // count of files to get size of
                                        );

  typedef int (__stdcall * GetSubFileVersionFunc)(
                                        int, // handle
                                        int // file_id
                                        );
  
  typedef int (__stdcall * GetSubfileDataFunc)(
                                        int, // handle
                                        int, // file_id
                                        void*, // buffer for storing data
                                        int, // 0
                                        int* // version
                                        );


  typedef int (__stdcall * CloseDatFileFunc)(
                                        int // handle
                                        );

  typedef int (__stdcall * PurgeSubFileDataFunc)(
                                        int, // handle
                                        int // file_id
                                        );

  typedef int (__stdcall * PutSubFileDataFunc)(
                                        int, // handle
                                        int, // file_id
                                        void*, // buffer with subfile data
                                        int, // 0
                                        int, // size of data in bytes
                                        int, // version
                                        int, // iteration
                                        bool // 0
                                        );

  typedef int (__stdcall * FlushFunc)(
                                        int // handle
                                        );
};


class DatExportApi {
 public:
  DatExportApi();

  int OpenDatFile(int handle, const char* filename, unsigned int flags);

  int GetNumSubfiles(int handle);

  void GetSubfileSizes(int handle, int* file_ids, int* size, int* iteration, int offset, int count);

  int GetSubfileVersion(int handle, int file_id);

  int GetSubfileData(int handle, int file_id, void* target_buf, int& version);

  void CloseDatFile(int handle);

  int PurgeSubfileData(int handle, int file_id);

  int PutSubfileData(int handle, int file_id, void* data, int offset, int size, int version, int iteration, bool compress = false);

  void Flush(int handle);

  ~DatExportApi();

 private:
  HMODULE datexport_dll_;

  FARPROC open_dat_file_addr_;
  volatile DatExportApiPrivate::OpenDatFileFunc open_dat_file_func_;
  FARPROC get_num_subfiles_addr_;
  volatile DatExportApiPrivate::GetNumSubfilesFunc get_num_subfiles_func_;
  FARPROC get_subfile_sizes_addr_;
  volatile DatExportApiPrivate::GetSubFileSizesFunc get_subfile_sizes_func_;
  FARPROC get_subfile_version_addr_;
  volatile DatExportApiPrivate::GetSubFileVersionFunc get_subfile_version_func_;
  FARPROC get_subfile_data_addr_;
  volatile DatExportApiPrivate::GetSubfileDataFunc get_subfile_data_func_;
  FARPROC close_dat_file_addr_;
  volatile DatExportApiPrivate::CloseDatFileFunc close_dat_file_func_;
  FARPROC purge_subfile_data_addr_;
  volatile DatExportApiPrivate::PurgeSubFileDataFunc purge_subfile_data_func_;
  FARPROC put_subfile_data_addr_;
  volatile DatExportApiPrivate::PutSubFileDataFunc put_subfile_data_func_;
  FARPROC flush_addr_;
  volatile DatExportApiPrivate::FlushFunc flush_func_; 
};