#pragma once

#include "util/Cloneable.h"

#include "util/simpleobject/AgString.h"
#include <vector>
#include <boost/shared_ptr.hpp>

class   Expression;

class Reference : public Cloneable
{
public:
    static AgString SCHEMA_FORM() { return "form"; }
    static AgString SCHEMA_TABLE() { return "table"; }
    static AgString SCHEMA_STATISTICS() { return "statistics"; }
    static AgString SCHEMA_ENVIRONMENT() { return "env"; }
    static AgString SCHEMA_PARENT() { return "parent"; }
    static AgString SCHEMA_MENU() { return "menu"; }

    // Deprecated in favour of new action reference syntax: context.path:action!
    // Support should be terminated in AggreGate 6
    static AgString SCHEMA_ACTION() { return "action"; }

    static const char EVENT_SIGN = '@';
    static const char ACTION_SIGN = '!';
    static const char PARAMS_BEGIN = '(';
    static const char PARAMS_END = ')';
    static const char SCHEMA_END = '/';
    static const char SERVER_END = '^';
    static const char CONTEXT_END = ':';
    static const char FIELD_BEGIN = '$';
    static const char ROW_BEGIN = '[';
    static const char ROW_END = ']';
    static const char PROPERTY_BEGIN = '#';

private:
    AgString image;
    AgString schema;
    AgString server;
    AgString context;
    AgString entity;
    int entityType;
    std::vector<boost::shared_ptr<void> >  parameters; // May contain Strings, Expressions and NULLs
    AgString field;
    AgString property;
    int row;
    void init();

protected:
    void ctor();
    void ctor(const AgString & source);
    void ctor(const AgString & server, const AgString & context);
    void ctor(const AgString & entity, int entityType, const AgString & field);
    void ctor(const AgString & context, const AgString & entity, int entityType, const AgString & field);
    void ctor(const AgString & context, const AgString & entity, int entityType);
    void ctor(const AgString & context, const AgString & function, std::vector<boost::shared_ptr<void> > parameters);

public:
    void parse(const AgString & source);

public:
    AgString getServer();
    AgString getContext();
    AgString getEntity();
    int getEntityType();
    AgString getField();
    std::vector<boost::shared_ptr<void> > getParameters();
    int getRow();
    AgString getSchema();
    AgString getProperty();
    AgString getImage();

private:
    AgString createImage();

public:
    AgString toString();
    void setContext(const AgString & context);
    void setEntity(const AgString & entity);
    void setEntityType(int entityType);
    void addParameter(const AgString & parameter);
    void addParameter(boost::shared_ptr<Expression> parameter);
    void setField(const AgString & field);
    void setProperty(const AgString & property);
    void setSchema(const AgString & schema);
    void setRow(int row);
    void setServer(const AgString & server);
    Reference* clone();
    bool equals(Reference* obj);

    Reference();
    Reference(const AgString & source);
    Reference(const AgString & server, const AgString & context);
    Reference(const AgString & entity, int entityType, const AgString & field);
    Reference(const AgString & context, const AgString & entity, int entityType, const AgString & field);
    Reference(const AgString & context, const AgString & entity, int entityType);
    Reference(const AgString & context, const AgString & function, std::vector<boost::shared_ptr<void> > parameters);
};
