#include <iostream>
using namespace std;

#include <stringconvert.h>
#include <stringtagparser.h>
#include <stringtagparsertest.h>
#include <tokenizer.h>

string stringtagparsertest::doc[] = 
{
  "",
  "Extract data between unique tags.",
  "Read a taged array",
  "Unit test extracting data between tags.",
  "Extracting non-unique taged elements.",
  "Extract C++ code commands and arguments."
};

void stringtagparsertest::test01()
{
  string str=
"<gameD2>\
  <startcolor>.324,.1,.8928</startcolor>\
  <matrixD2>\
    <m>25</m>\
    <n>23</n>\
  </matrixD2>\
  <settings>\
    <walls>1</walls>\
    <pipes>0</pipes>\
  </settings>\
</gameD2>\
";

  stringtagparser sp((stringc)str);

  //sp.data("matrixD2");

  cout << "Inside walls tag." << endl;
  cout << sp.data("walls") << endl;
  cout << "Inside startcolor tag." << endl;
  cout << sp.data("startcolor") << endl;
  cout << "Inside settings tag." << endl;
  cout << sp.data("settings") << endl;

  cout << endl;
  cout << "Including the tags matrixD2 with * delimeters" << endl;
  cout << "*" << sp.data_with_tags("matrixD2") << "*" << endl;

}

void stringtagparsertest::test02()
{
  string str=
"<data>\
  <parts>\
    <n>3</n>\
    <1>\
      <item>29960-2</item>\
      <quantity>2</quantity>\
      <desc>2GB PC5300 DDR2 667 MHz SO-Dim</desc>\
      <sn>zsd283884</sn>\
    </1>\
    <2>\
      <item>si393-02</item>\
      <quantity>1</quantity>\
      <desc>Logitech headset</desc>\
      <sn></sn>\
    </2>\
    <3>\
      <item>jsie-38291-13</item>\
      <quantity>1</quantity>\
      <desc>Netgear 3G Broadband Wireless Router MBR624GU</desc>\
      <sn></sn>\
    </3>\
  </parts>\
</data>";

//  stringtagparser sp(str);
//  cout << sp.data("data","parts","n") << endl;

  string parts = stringtagparser(str).data("data","parts");
  uint n;
  stringtagparser sp(parts);
  stringfrom(n,sp.data("n"));

  cout << n << endl;
  for (uint i=1; i<=n; ++i)
  {
    cout << "item: " << sp.data(stringto(i),"item") << endl;
    cout << "description: " << sp.data(stringto(i),"desc") << endl;
  }
}


int stringtagparsertest::unittest01()
{
  string str=
"<gameD2>\
  <startcolor>.324,.1,.8928</startcolor>\
  <matrixD2>\
    <m>25</m>\
    <n>23</n>\
  </matrixD2>\
  <settings>\
    <walls>1</walls>\
    <pipes>0</pipes>\
  </settings>\
</gameD2>\
";

  string ans1="1";
  string ans2=".324,.1,.8928";
  string ans3="\
    <walls>1</walls>\
    <pipes>0</pipes>\
  ";
  string ans4="<matrixD2>\
    <m>25</m>\
    <n>23</n>\
  </matrixD2>";

  stringtagparser sp(str);

  assertreturnT(sp.data("walls")==ans1,1);
  assertreturnT(sp.data("startcolor")==ans2,1);
  assertreturnT(sp.data("settings")==ans3,1);

//cout << "*" << sp.data_with_tags("matrixD2") << "*" << endl;
//cout << "*" << ans4 << "*" << endl;

  assertreturnT(sp.data_with_tags("matrixD2")==ans4,1);

  return 0;
}

void stringtagparsertest::test03()
{
  cout << stringtagparsertest::doc[4] << endl;
 
  string str=
"<data>\
  <funkyobj>\
    <obj>3 4 2</obj>\
    <obj>1 13 2</obj>\
    <obj>9 0 2</obj>\
    <obj>7 20 -2</obj>\
  </funkyobj>\
</data>";

  cout << "str=" << str << endl;
  cout << "stringtagiter" << endl;

  stringtagiter i(str,"obj");

  for (i.reset(); !i; ++i)
  {
//cout << "#" << endl;
    cout << i() << endl;
  }

}

void stringtagparsertest::test04()
{
  cout << "Example of using parser and tokenizer." << endl;
  cout << "Extracting C++ source code funtion calls" << endl;

  string str="<gobj>  glPushAttrib(GL_CURRENT_BIT); glPushAttrib(GL_LIGHTING_BIT); glDisable(GL_LIGHTING); glBegin(GL_LINES); glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(1.0,0.0,0.0); glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,1.0,0.0); glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,1.0); glEnd(); glPopAttrib(); glPopAttrib(); </gobj>";

  cout << "str=" << str;
  stringtagparser p1(str);
  string s2(p1.data("gobj"));
  //cout << s2 << endl;

  tokenizer ss(s2);
  ss.subtract(";"); // split string into substrings
  ss.trim(); 
  ss.remove_if();  // delete empty strings
  // At this point all strings should be 
  //   of the form <name>(arg with commas)
cout << "***" << endl;
  for ( ss.reset(); !ss; ++ss)
  {
    string& s(*ss);
    replace(s.begin(),s.end(),',',' ');
    replace(s.begin(),s.end(),'(',' ');
    replace(s.begin(),s.end(),')',' ');
  }
  for ( ss.reset(); !ss; ++ss)
    { cout << ss() << endl; }

}

int stringtagparsertest::unittest02()
{
  cout << "" << endl;
  string str=
"<mkerrors>\
<abc> </abc>\
<abcd></abcd>\
<currentsettings>\
  <state> </state>\
  <libraries></libraries>\
  <projectdirectory></projectdirectory>\
</currentsettings>\
<configuration>\
<linux> <libraries>-lGL -lGLU -lglut</libraries></linux>\
<config001><libraries>/usr/local/lib/libntl.a<libaries>\
</config001>\
</configuration>\
</mkerrors>";

  stringtagparser sp(str);

  string s;
  string tag;

  cout << "Test with one space in the tag" << endln;
  tag="abc";
  cout << SHOW(tag) << endln;
  s = sp.data(tag);
cout << "*" << SHOW(s) << "*" <<  endl;

  spacerdelete<>()[s];
  assertreturnOS( (bool)spacerdelete<>()[s] );
  cout << SHOW3(s) << endln;

  assertreturnOS(sp.tagfound);
  cout << SHOW(sp.tagfound) << endln;

  cout << "Test with no space in the tag" << endln;
  tag="abcd";
  cout << SHOW(tag) << endl;
  s = sp.data(tag);
cout << "*" << SHOW(s) << "*" <<  endl;

  assertreturnOS( (bool)spacerdelete<>()[s] );

  cout << SHOW3(s) << endln;
  assertreturnOS(sp.tagfound);

  tag="nonexistant_tag";
  s = sp.data(tag);

  assertreturnOS(!sp.tagfound);

  return 0;
}






