#ifndef _WB_MODEL_FILE_H_
#define _WB_MODEL_FILE_H_

#include "wb_backend_public_interface.h"

#include <string>
#include "grtpp.h"

#include "grts/structs.workbench.h"

#include <cairo.h>

namespace wb {
  class MYSQLWBBACKEND_PUBLIC_FUNC ModelFile : public sigc::trackable
  {
  public:
    ModelFile();
    ~ModelFile();

    void create();
    void open(const std::string &path);

    void cleanup();

    void save_to(const std::string &path);

    bool has_unsaved_changes() { return _dirty; }


    workbench_DocumentRef retrieve_document(grt::GRT *grt);
    
    std::list<std::string> get_load_warnings() const { return _load_warnings; }

    void store_document(grt::GRT *grt, const workbench_DocumentRef &doc);


    std::list<std::string> get_file_list(const std::string &prefixdir= "");
    bool has_file(const std::string &name);

    std::string add_image_file(const std::string &path);
    std::string add_script_file(const std::string &path);
    std::string add_note_file(const std::string &path);
    void delete_file(const std::string &path);
    bool undelete_file(const std::string &path);

    void set_file_contents(const std::string &path, const std::string &data);
    void set_file_contents(const std::string &path, const char *data, size_t size);
    std::string get_file_contents(const std::string &path);

    std::string get_path_for(const std::string &file);

    static void copy_file(const std::string &path, const std::string &dest);

    void copy_file_to(const std::string &file, const std::string &dest);

    std::string in_disk_document_version() const { return _loaded_version; }
    
    // image management
    cairo_surface_t *get_image(const std::string &path);


    sigc::signal<void> signal_changed() { return _changed_signal; }

  private:
    GStaticRecMutex _mutex;
    std::string _temp_dir; //< temporary files directory
    std::string _content_dir; //< path for directory where document contents are stored in disk
    std::list<std::string> _delete_queue; //< files marked for deletion
    std::string _loaded_version; //< version of the model file as stored in disk
    
    std::list<std::string> _load_warnings; //< warnings from loaded model
    
    bool _dirty;

    sigc::signal<void> _changed_signal;

    workbench_DocumentRef unserialize_document(grt::GRT *grt, xmlDocPtr xmldoc, const std::string &path);

    
  private:    
    bool attempt_xml_document_upgrade(xmlDocPtr xmldoc, const std::string &version);
    workbench_DocumentRef attempt_document_upgrade(const workbench_DocumentRef &doc,
      xmlDocPtr xmldoc, const std::string &version);
    void cleanup_upgrade_data();
    
    void check_and_fix_inconsistencies(xmlDocPtr xmldoc, const std::string &version);
    
    void check_and_fix_inconsistencies(const workbench_DocumentRef &doc, const std::string &version);

  private:
    void unpack_zip(const std::string &zipfile, const std::string &destdir);
    void pack_zip(const std::string &zipfile, const std::string &destdir);
  };
};


#endif
