#ifndef __Tag_h__
#define __Tag_h__

#include "ZString.h"
#include "MString.h"
#include "Global.h"
#include <map>

///
///
///

namespace jet {

///
///
///
   
   class Tag : public coreutils::ZString {

    public:
      Tag(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent = NULL, Tag *local = NULL, coreutils::ZString splitTagName = ""); //!>Constructor
      virtual ~Tag();

      coreutils::MString getVariable(coreutils::ZString &variable, bool inContainer = false); //!>retrieve a vairable value from a text string cotontaining a variable name.

      coreutils::MString resolveKeyword(coreutils::ZString keyword);
      std::map<coreutils::MString, coreutils::MString> variables;
      std::map<coreutils::MString, coreutils::MString> keywords;
      coreutils::ZString name;
      coreutils::ZString container;
      coreutils::ZString container2;
      Global &global;
      Tag *parent;
      Tag *local;

    protected:
      bool hasContainer = false;
      bool hasContainer2 = false;
      bool keywordDefined(coreutils::ZString variable);
      void parseContainer(coreutils::ZString &in, coreutils::MString &out, coreutils::ZString container2 = NULL, bool topLevel =  false);
      void processContainer(coreutils::ZString &container, coreutils::ZString container2 = NULL, bool topLevel = false);
      void copyContainer(coreutils::ZString &in, coreutils::MString &out);

      coreutils::MString &parentOut;
      coreutils::MString out;

      bool output = true;
      bool evaluate = true;
      bool filterBlankLines = false;
      bool trimLines = false;
      bool cleanWhitespace = false;

      void renderVariableName(coreutils::ZString &variable, coreutils::MString &name, coreutils::MString &modifier);
      void storeVariable(coreutils::ZString variable, coreutils::MString value, coreutils::ZString scope);
      void storeVariable(coreutils::ZString variable);
      
    private:
      bool containerOnly = false;
      coreutils::ZString splitTagName;

      int skipBlankLine(coreutils::ZString in);

      void scanContainer(coreutils::ZString &in);
      bool ifNested(coreutils::ZString &in);
      bool ifTagName(coreutils::ZString &in, const char *tag);
      bool ifTagName(coreutils::ZString &in);
      bool ifTagDefined(coreutils::ZString &in, coreutils::ZString &tag);
      bool ifEndTagName(coreutils::ZString &in);
      bool ifSplitTagName(coreutils::ZString &in);
      
      coreutils::MString processModifier(coreutils::MString &value, coreutils::MString &modifier);
   };

}

#endif
