#include "projectmap.h"

#include <akaxiso/akaxiso.h>
#include <iostream>
#include <stdlib.h>

static void setup_members(pj::MemberMap &members) {

  // Member
  pj::MemberPair epi("Episteme", "God of dragon");
  members.insert(epi);

  pj::MemberPair shibu("Shibukawa", "Artistic director");
  members.insert(shibu);

  pj::MemberPair doukeshi("Doukeshi", "Wraith of the trickstar");
  members.insert(doukeshi);

  pj::MemberPair ahiru("Ahiru", "BCB guru");
  members.insert(ahiru);

  pj::MemberPair shelarcy("shelarcy", "RELAX NG Evangelist");
  members.insert(shelarcy);

  pj::MemberPair ando("Ando(&o)", "Sorcerer of macuppa");
  members.insert(ando);

  pj::MemberPair morino("Morino", "Farmer");
  members.insert(morino);

}


void serialize(const std::string &docname) {
  
  // Get the root node.
  pj::OrderedTeam team;

  team.name_ = "Cuppa project team";
  team.url_ = "http://unittest.org";

  setup_members(team.members_);

  // Create Document instance.
  aka::xml_serializer ser;
  ser.using_prefix("cuppa");

  // Serialize.
  ser.serialize(team, docname, std::cout);

}

void parse() {
  // Parse
  aka::xml_parser parser;
  aka::document doc;
  try {
    doc = parser.parse_stdin();
  }
  catch ( const std::exception &e) {
    std::cerr << e.what() << std::endl;
    exit(1);
  }
  catch ( ... ) {
    std::cerr << "Parse error detected." << std::endl;
    exit(1);
  }
    
  // Check root tagname to confirm the root class.
  if (aka::document_of(doc, "cuppa:simplecontents_map") ||
      aka::document_of(doc, "cuppa:sequence_map")) {
    std::cout << "The type of the parsed document is\"" 
              << doc.get_name() << "\"." << std::endl;
  }
  else {
    std::cerr << "Unknown document type." << std::endl;
    exit(1);
  }

  // Get the root node.
  pj::OrderedTeam  *team = aka::root_cast<pj::OrderedTeam>(doc);
  pj::MemberMap &members = team->members_;

  // Title
  std::cout << "Member list of '" << team->name_ << "'(" << team->url_ << ')' << std::endl;

  // Row for each member.
  for (pj::MemberMap::iterator it = members.begin(); it != members.end(); ++it) 
    std::cout << "name : " << it->first 
              << std::string("                    ").substr(it->first.size())
              << "title : " << it->second << std::endl;

}

void usage() {
  std::cout << "project [-s1|-s2|-p|-h]" << std::endl
            << "  -s1: serialize member as simpleContents." << std::endl
            << "  -s2: serialize member as sequence." << std::endl
            << "  -p : parse.    " << std::endl
            << "  -h : show this usage." << std::endl;
}


int main(int argc, const char* argv[]){
  
  aka::initialize();

  // Initialize Project classes defined in project.h.
  aka::xmlns("cuppa", "http://unittest.org/akaxiso/memberlist");
  aka::doctype("cuppa:simplecontents_map", pj::OrderedSimpleContentTeamLeaf());
  aka::doctype("cuppa:sequence_map", pj::OrderedSequenceTeamLeaf());
  

  if (argc != 2) {
    usage();
    return 1;
  }

  std::string arg = argv[1];

  if (arg == "-s1")
    serialize("cuppa:simplecontents_map");
  else if (arg == "-s2")
    serialize("cuppa:sequence_map");
  else if (arg == "-p")
    parse();
  else {
    usage();
    return 1;
  }

  aka::uninitialize();
  return 0;
}
