ifndef SASS_CONTEXT_H define SASS_CONTEXT_H

// sass.hpp must go before all system headers to get the // __EXTENSIONS__ fix on Solaris. include “sass.hpp” include “ast.hpp”

define BUFFERSIZE 255 include “b64/encode.h”

include “sass_context.hpp” include “stylesheet.hpp” include “plugins.hpp” include “output.hpp”

namespace Sass {

class Context {
public:
  void import_url (Import* imp, sass::string load_path, const sass::string& ctx_path);
  bool call_headers(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp)
  { return call_loader(load_path, ctx_path, pstate, imp, c_headers, false); };
  bool call_importers(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp)
  { return call_loader(load_path, ctx_path, pstate, imp, c_importers, true); };

private:
  bool call_loader(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp, sass::vector<Sass_Importer_Entry> importers, bool only_one = true);

public:
  const sass::string CWD;
  struct Sass_Options& c_options;
  sass::string entry_path;
  size_t head_imports;
  Plugins plugins;
  Output emitter;

  // generic ast node garbage container
  // used to avoid possible circular refs
  CallStack ast_gc;
  // resources add under our control
  // these are guaranteed to be freed
  sass::vector<char*> strings;
  sass::vector<Resource> resources;
  std::map<const sass::string, StyleSheet> sheets;
  ImporterStack import_stack;
  sass::vector<Sass_Callee> callee_stack;
  sass::vector<Backtrace> traces;
  Extender extender;

  struct Sass_Compiler* c_compiler;

  // absolute paths to includes
  sass::vector<sass::string> included_files;
  // relative includes for sourcemap
  sass::vector<sass::string> srcmap_links;
  // vectors above have same size

  sass::vector<sass::string> plugin_paths; // relative paths to load plugins
  sass::vector<sass::string> include_paths; // lookup paths for includes

  void apply_custom_headers(Block_Obj root, const char* path, SourceSpan pstate);

  sass::vector<Sass_Importer_Entry> c_headers;
  sass::vector<Sass_Importer_Entry> c_importers;
  sass::vector<Sass_Function_Entry> c_functions;

  void add_c_header(Sass_Importer_Entry header);
  void add_c_importer(Sass_Importer_Entry importer);
  void add_c_function(Sass_Function_Entry function);

  const sass::string indent; // String to be used for indentation
  const sass::string linefeed; // String to be used for line feeds
  const sass::string input_path; // for relative paths in src-map
  const sass::string output_path; // for relative paths to the output
  const sass::string source_map_file; // path to source map file (enables feature)
  const sass::string source_map_root; // path for sourceRoot property (pass-through)

  virtual ~Context();
  Context(struct Sass_Context&);
  virtual Block_Obj parse() = 0;
  virtual Block_Obj compile();
  virtual char* render(Block_Obj root);
  virtual char* render_srcmap();

  void register_resource(const Include&, const Resource&);
  void register_resource(const Include&, const Resource&, SourceSpan&);
  sass::vector<Include> find_includes(const Importer& import);
  Include load_import(const Importer&, SourceSpan pstate);

  Sass_Output_Style output_style() { return c_options.output_style; };
  sass::vector<sass::string> get_included_files(bool skip = false, size_t headers = 0);

private:
  void collect_plugin_paths(const char* paths_str);
  void collect_plugin_paths(string_list* paths_array);
  void collect_include_paths(const char* paths_str);
  void collect_include_paths(string_list* paths_array);
  sass::string format_embedded_source_map();
  sass::string format_source_mapping_url(const sass::string& out_path);

  // void register_built_in_functions(Env* env);
  // void register_function(Signature sig, Native_Function f, Env* env);
  // void register_function(Signature sig, Native_Function f, size_t arity, Env* env);
  // void register_overload_stub(sass::string name, Env* env);

public:
  const sass::string& cwd() { return CWD; };
};

class File_Context : public Context {
public:
  File_Context(struct Sass_File_Context& ctx)
  : Context(ctx)
  { }
  virtual ~File_Context();
  virtual Block_Obj parse();
};

class Data_Context : public Context {
public:
  char* source_c_str;
  char* srcmap_c_str;
  Data_Context(struct Sass_Data_Context& ctx)
  : Context(ctx)
  {
    source_c_str       = ctx.source_string;
    srcmap_c_str       = ctx.srcmap_string;
    ctx.source_string = 0; // passed away
    ctx.srcmap_string = 0; // passed away
  }
  virtual ~Data_Context();
  virtual Block_Obj parse();
};

}

endif