#define SASS_CONTEXTUALIZE

#ifndef SASS_ENVIRONMENT
#include "environment.hpp"
#endif

#ifndef SASS_OPERATION
#include "operation.hpp"
#endif

namespace Sass {
  class AST_Node;
  class Selector;
  class Selector_Schema;
  class Selector_List;
  class Complex_Selector;
  class Compound_Selector;
  class Negated_Selector;
  class Pseudo_Selector;
  class Attribute_Selector;
  class Selector_Qualifier;
  class Type_Selector;
  class Selector_Placeholder;
  class Selector_Reference;
  class Simple_Selector;
  struct Context;
  class Eval;
  struct Backtrace;

  typedef Environment<AST_Node*> Env;

  class Contextualize : public Operation_CRTP<Selector*, Contextualize> {

    Context&   ctx;
    Eval*      eval;
    Env*       env;
    Selector*  parent;
    Backtrace* backtrace;

    Selector* fallback_impl(AST_Node* n);

  public:
    Selector* placeholder;
    Selector* extender;
    Contextualize(Context&, Eval*, Env*, Backtrace*, Selector* placeholder = 0, Selector* extender = 0);
    virtual ~Contextualize();
    Contextualize* with(Selector*, Env*, Backtrace*, Selector* placeholder = 0, Selector* extender = 0);
    using Operation<Selector*>::operator();

    Selector* operator()(Selector_Schema*);
    Selector* operator()(Selector_List*);
    Selector* operator()(Complex_Selector*);
    Selector* operator()(Compound_Selector*);
    Selector* operator()(Negated_Selector*);
    Selector* operator()(Pseudo_Selector*);
    Selector* operator()(Attribute_Selector*);
    Selector* operator()(Selector_Qualifier*);
    Selector* operator()(Type_Selector*);
    Selector* operator()(Selector_Placeholder*);
    Selector* operator()(Selector_Reference*);

    template <typename U>
    Selector* fallback(U x) { return fallback_impl(x); }
  };
}
