#include <akaxiso/akaxiso.h>
#include <akaxiso/content_model.h>
#include <iostream>
#include <iomanip>


namespace {

  struct chars {
    std::string encoding_;
    std::string text_;
  };

  struct chars_leaf : public aka::sequence<chars, chars_leaf> {
    void model() {
      member("encoding", &chars::encoding_);
      member("text", &chars::text_);
    }
  };

}

void dump_string(const std::string &doc) {

  for (std::string::size_type pos = 0; pos < doc.size(); ++pos)
    std::cout << std::setw(2) << std::setfill('0') << std::hex << ((int)doc[pos] & 0xffUL) << " ";
  std::cout << std::endl;

}



void parse(const std::string &filename, const std::string &encoding) {

#ifdef USE_XERCESC
  {
    aka::use_xerces_transcoder(true); // If USE_XERCESC is defined, Default is true.
                                      // You don't have to specify.
    std::cout << std::endl
	      << "Using Xerces-C++ transcoder..." << std::endl
	      << std::endl;
    std::ostringstream ostm;

    aka::use_xerces_transcoder(true);
    aka::xerces_parser parser;
    aka::document doc = parser.parse_file(filename);
    
    aka::xml_serializer ser(encoding);
    ser.serialize(doc, std::cout);

    ser.serialize(doc, ostm);
    std::cout << "Dump..." << std::endl;
    dump_string(ostm.rdbuf()->str());

    aka::use_xerces_transcoder(false);
  }
#endif

  {
    std::cout << std::endl
	      << "Using babel translator..." << std::endl
	      << std::endl;

    std::ostringstream ostm;
    aka::yggxml_parser parser;
    aka::document doc = parser.parse_file(filename);
    aka::xml_serializer ser(encoding);
    ser.serialize(doc, std::cout);

    ser.serialize(doc, ostm);
    std::cout << "Dump..." << std::endl;
    dump_string(ostm.rdbuf()->str());
  }

}


void usage() {
  std::cout << "encoding [filename] [encoding]" << std::endl
            << "  -h : show this usage." << std::endl;
}


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

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

  parse(argv[1], argv[2]);

  aka::uninitialize();
  return 0;
}
