/************************************

  "waka" is a Japanese poetry 
         composed of 31 syllables. 

  (c) 2005 Pixel-Apes.

  -----------------------------------

  Generic token class
  (and its empty one pair).

  It is base of all tokens.

  refactoring issues:
  * ".separateFromNext()" is called each time ".toHtml()" get called.
    I think it is possible to optimize this step

*************************************/

function wakaToken() { }
wakaToken.prototype = 
{
   _data : "",          // custom data struct
   _html : false,       // compiled html result
   _compiled  : false,  // is that ^^ result ready?

   _prev   : false, // previous token (sibling), if any
   _parent : false, // parent token, if any
   _tree   : [],    // child tokens, if any


   // binds this token instance to originating formatter
   bind : function( wf )
   {
     this.wf = wf;
   },

   // --------------- STATIC: -----------------
   // part for parent formatter, used to break
   // incoming text into sequence of tokens
   getRegexpPart : function()
   {
     return "";
   },

   // detects, if given text is a current token, then forms context-dependent struct
   // else returns false;
   is : function( outerText )
   {
     return false;
   },
   // --------------- /STATIC -----------------

   // sets next preset for recursive polyformatting
   // used only for plain wakaTokens 
   _nextPreset : false,
   setNextPreset : function( preset )
   {
     this._nextPreset = preset;
   },

   // build from freeformed wiki-text
   parse : function( outerText )
   {
     this.build(this.is( outerText ));
   },

   // build from context-dependent struct
   // return false, if this token was glued up to parent one
   build : function( dataStruct, previousToken )
   {
     // no build performed
     if (dataStruct === false) return;

     this._compiled = false;
     this._data = dataStruct;
     this._prev = previousToken;
     this._parent = false;
     this._tree = [];

     // this hack is used in some sophisticated tokens
     // to get rid of unnecessary newlines
     if (previousToken && previousToken.hack_separateTrimNextNewline && this._data.replace)
       this._data = this._data.replace( /^\n/, "" );

     if (this._glue()) return false;
     else return this._flattenTree();
   },

   // private abstract: preprocess tree after build
   // should be overriden to process subtree and gluein it in main parsing sequence
   _flattenTree : function()
   {
     return [ this ];
   },

   // private: glue to a previous token
   // returns true, if this token was glued up to parent one
   _glue : function()
   {
     return false;
   },

   // glues given token as child. returns true on success
   glueChild : function( tokenChild )
   {
     if (this._tree.length > 0)
       tokenChild._prev = this._tree[ this._tree.length-1 ];
     else 
       tokenChild._prev = false;

     if (!tokenChild._glue())
     {
       tokenChild._parent = this;
       this._tree[ this._tree.length ] = tokenChild;
     }

     return true;
   },

   // private: compile from struct to html
   _compile : function()
   {
     if (this._nextPreset)
       this._html = this.wf.format( this._data, this._nextPreset );
     else
       this._html = this._data;
     this._compiled = true;
   }, 

   // returns separation from a given "next"
   separateFromNext : function( next )
   {
     return "";
   },

   // pretty clear: returns HTML appearance of this token (and its childs)
   toHtml : function()
   {
     var sep = "";
     if (this._prev) sep=this._prev.separateFromNext(this);

     if (!this._compiled) this._compile();

     return sep + this._html;
   },

   // special functionality for export content
   toText : function()
   {
     if (typeof this._data == "string") return this._data;
     else                               return this._data.text;
   },

   // simple functions to end up with class definition.
   undef : function( param ) 
   { return param; },
   trim  : function( data )
   { return data.replace( /^\s+/, "" ).replace( /\s+$/, "" ); }
}

// note that!
wakaToken.prototype.constructor = wakaToken;



// --------------------------------------------------------
// --- Empty token. 
// --- Used for skipping whitespace in some formatting 
// --- presets such as table
function wakaEmpty() {}
         wakaEmpty.prototype = new wakaToken();
         wakaEmpty.prototype.constructor = 
         wakaEmpty;
wakaEmpty.prototype._glue   = function()
{
  return true; // always say it is glued up
}
wakaEmpty.prototype._compile   = function()
{
  this._html = ""; // never returns html
}

