#include <iostream>
#include <fstream>
#include "customers.hxx"

#include <xercesc/dom/DOM.hpp>
#include <xsd/cxx/xml/sax/std-input-source.hxx>
#include <xsd/cxx/xml/string.hxx>

#include <xqilla/xqilla-simple.hpp>
#include <xqilla/simple-api/XQillaConfiguration.hpp>
#include <xqilla/exceptions/XQException.hpp>
#include <xqilla/context/impl/XQContextImpl.hpp>
#include <xqilla/events/SequenceBuilder.hpp>

using namespace std;
using namespace xercesc;
namespace xml = xsd::cxx::xml;

std::string tostr( const XMLCh* xc )
{
    if( !xc )
        return "";
        
    char* native_cstr = XMLString::transcode( xc );
    string ret = native_cstr;
    XMLString::release( &native_cstr );
    return ret;
}

int
main (int argc, char* argv[])
{
    try
    {
        //
        // The XQuery to find our customer
        // 
        std::string xquery_string = "";
        {
            stringstream ss;
            ss << "<customers>"
               << "{"
               << "  for $c in //customer"
               << "  where $c/middle-name = \"Montgomery\""
               << "  return $c"
               << "}"
               << "</customers>";
            xquery_string = ss.str();
        }
        

        //
        // Evaluate XQuery expression
        //
        XQilla::Language language = XQilla::XQUERY;
        XQilla xqilla;
        static XercesConfiguration xcon;
        XQContextImpl* stcontext = dynamic_cast<XQContextImpl*>(xqilla.createContext());
        AutoDelete<DynamicContext> ctxGuard( stcontext->createModuleContext(stcontext->getMemoryManager()));
        DynamicContext* context = ctxGuard.get();
        AutoDelete<XQQuery> query( xqilla.parse(X(xquery_string.c_str()),
                                                ctxGuard.adopt(),
                                                0, language ));

        //
        // bind the XML document to the query
        //
        {
            Sequence seq;
            seq = context->resolveDocument(X( argv[1] ), 0);
            if(!seq.isEmpty() && seq.first()->isNode())
            {
                context->setContextItem(seq.first());
                context->setContextPosition(1);
                context->setContextSize(1);
            }
        }

        context->setDefaultURIResolver(
            xcon.createDefaultURIResolver( context->getMemoryManager() ),
            false );
        SequenceBuilder* xseqBuilder = xcon.createSequenceBuilder( context );
        query->execute( xseqBuilder, context );
        Sequence seq = xseqBuilder->getSequence();
        if( seq.isEmpty() )
        {
            cerr << "no result!" << endl;
        }
        else
        {
            //
            // OK, we have somebody, show the first result from
            // the XQuery.
            //
            Item::Ptr item = seq.first();
            DOMDocument* doc = (DOMDocument*)item->getInterface( XercesConfiguration::gXerces );
            DOMNode* node = doc->getDocumentElement();
                
            // Convert to C++ objects...
            auto_ptr<customers_t> all_customers(
                customers( *doc,
                           0
                           | xml_schema::flags::dont_initialize
                    ));
            cerr << "all_customers.size:" << all_customers->customer().size() << endl;
            if( !all_customers->customer().empty() )
            {
                customer_t c = all_customers->customer().front();
                cout << "first name:" << c.first_name()
                     << " sirname:"   << c.sir_name()
                     << endl;
            }
        }
    }
    catch (const xml_schema::exception& e)
    {
        cerr << e << endl;
        return 1;
    }
    catch (const xercesc_2_8::DOMException& e)
    {
        cerr << tostr(e.msg) << endl;
        return 1;
    }
    catch( XQException& e )
    {
        cerr << tostr(e.getError()) << endl;
        return 1;
    }
    
}

