#include "basket.h"

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

void serialize() {

  basket bk;

  xiso::leaf<basket>::moc choice(bk);

  choice.push_back(fruit("banana"), "fruit");
  choice.push_back(fruit("orange"), "fruit");
  choice.push_back(vesitable("parsley"), "vesitable");
  choice.push_back(vesitable("cucumber"), "vesitable");

  eggs eggs;
  eggs.push_back(egg(30.)); // 30 g egg.
  eggs.push_back(egg(40.)); // 40 g egg.

  choice.push_back(eggs, "egg");

  aka::xml_serializer ser;

  ser.serialize(bk, "basket", std::cout);

}

void parse() {

  aka::document doc;
  aka::xml_parser parser;
  
  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, "basket")) {
    std::cerr << "Unknown document(" << doc.get_name() << ")." << std::endl;
    exit(1);
  }

  // Get the root node.
  basket  *root = aka::root_cast<basket>(doc);

  for (basket::iterator it = root->begin(); it != root->end(); ++it) {
    if (aka::item_of(*it, "fruit"))
      std::cout << "Fruit " << aka::item_cast<std::string>(*it) << std::endl;
    else if (aka::item_of(*it, "vesitable"))
      std::cout << "Vesitable " << aka::item_cast<std::string>(*it) << std::endl;
    else if (aka::item_of(*it, "egg")) {
      eggs & es = aka::item_cast<eggs>(*it);
      for (eggs::const_iterator it = es.begin(); it != es.end(); ++it)
        std::cout << "egg(" << it->weight_ << "g)" << std::endl;
    }
  }
}


void usage() {
  std::cout << "project [-s|-p|-h]" << std::endl
            << "  -s : serialize." << std::endl
            << "  -p : parse.    " << std::endl
            << "  -h : show this usage." << std::endl;
}


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

  // Initialize document.
  aka::doctype("basket", xiso::leaf<basket>()).set_occurrence(0, aka::unbounded);

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

  std::string arg = argv[1];

  if (arg == "-s")
    serialize();
  else if (arg == "-p")
    parse();
  else {
    usage();
    return 1;
  }

  aka::uninitialize();
  return 0;
}
