#ifndef __XGENSEEXPR_H__
#define __XGENSEEXPR_H__
#include <vector>
#include <shader.h>
#include <SePlatform.h>
#include <SeExpression.h>
namespace XGenMR
{
class SeExprShader
{
public:
    
    SeExprShader();
    ~SeExprShader();
    
    struct Attr
    {
        miTag name; 
        miVector vec;
    };
    
    struct Params
    {
        miTag expression;   
        Attr attrs[8];      
        miTag customs;      
    };
    class MRSeExpression; 
    
    
    
    class MRSeExprVarRef : public SeExprVarRef
    {
    public:
        MRSeExprVarRef(MRSeExpression* parent=NULL, const char* in_name="", bool in_isVector=true )
        {
            m_parent = parent;
            m_name = in_name;
            m_isVector = in_isVector;
        }
        virtual ~MRSeExprVarRef() {}
        virtual bool isVec();
        virtual void eval(const SeExprVarNode* node, SeVec3d& result);
    private:
        MRSeExpression* m_parent;
        std::string m_name;
        bool m_isVector;
    };
    
    class MRSeExpression : public SeExpression
    {
    public:
        
        typedef std::map<std::string, std::pair<SeVec3d,bool> > TLSValues;
        
        typedef std::pair<miTag,MRSeExpression::TLSValues> TLSMapPair;
        typedef std::map<miTag,MRSeExpression::TLSValues> TLSMap;
        typedef std::pair<TLSMap::iterator,bool> TLSMapInsert;
        
        MRSeExpression()
        {
            m_tls = NULL;
        }
        ~MRSeExpression()
        {
            m_tls = NULL; 
        }
        
        void setTLSValues(TLSValues* in_values )
        {
            m_tls = in_values;
        }
        
        const TLSValues* getTLSValues( )
        {
            return m_tls;
        }
        
        void createRefs();
        virtual SeExprVarRef* resolveVar(const std::string& ) const;
        TLSValues* m_tls; 
        std::map<std::string,MRSeExprVarRef> m_refs;
    };
    
    
    
    
    
    typedef std::map<miTag,UserDataFormat> UserDataFormatMap;
    
    
    struct  TLSData
    {
        MRSeExpression::TLSMap  m_cacheTLS;     
        MRSeExpression          m_expression;   
        UserDataFormatMap       m_fmts;         
    };
    
    void init( miState* state, Params* paras );
    miBoolean execute( miVector* result, miState* state, Params* paras );
private:
    
    std::string m_strExpression;            
    std::vector<std::string> m_strNames;    
    
    
    static bool findInstanceUserData( miState* state, miTag in_instance, miTag& out_user );
    static bool findPlaceholderItemUserData( miState* state, miTag in_instance, miTag& out_user );
    static bool findXGMRUserData( miState* state, miTag in_user, char*& out_string, int& out_size );
    static bool findXGMRUserDataOnInstance( miState* state, miTag in_instance, char*& out_string, int& out_size );
    bool recFindUserDataFormat( miState* state, MRSeExpression::TLSValues& values, UserDataFormatMap& fmts );
    bool findUserDataFormat( miState* state, miTag tagInstance, MRSeExpression::TLSValues& values, UserDataFormatMap& fmts );
    bool recFindUserDataScalars( miState* state, const float*& scalars, UserDataFormatMap& fmts );
    bool findUserDataScalars( miState* state, miTag tagInstance, const float*& scalars, UserDataFormatMap& fmts );
    
    
    MRSeExpression::TLSValues m_declValues;
    
    MRSeExpression* m_pExpression; 
};
}
#endif