#include <fstream>
#include <cstdio>

#include "myDbEnv.hpp"
#include "myXmlContainer.hpp"

using namespace DbXml;

void usage()
{
        std::cerr <<   "This program performs various XPath queries against a DBXML container. You should\n"
                  << "pre-load the container using loadExamplesData.[sh|cmd] before running this example. You\n"
                  << "are only required to pass this command the path location of the database environment\n"
                  << "that you specified when you pre-loaded the examples data:\n\n"

                  << "\t-h <dbenv directory>" << std::endl;
        exit( -1 );
}

void doQuery( XmlContainer &container, const std::string &XPath )
{
    ////////////////////////////////////////////////////////////////////////
    //////  Performs a simple XPath query (no context) against the   ///////
    //////  provided container.                                      ///////
    ////////////////////////////////////////////////////////////////////////

    ///// some defensive code eliminated for clarity //

    // Perform the query. Result type is by default Result Document
    
    try {
        std::cout << "Exercising query '" << XPath << "' " << std::endl;
        std::cout << "Return to continue: ";
        getc(stdin);

        XmlResults results( container.queryWithXPath(0, XPath, 0 ) );
        XmlValue value;
        int count = 0;
        while( results.next(value) )
        {
            // Obtain the value as a string and print it to stdout
            std::cout << value.asString( 0 ) << std::endl;
            count ++;
        }

        std::cout << results.size() << " objects returned for expression '" << XPath << "'\n" << std::endl;

    }
    catch(XmlException &e)
    {
        std::cerr << "Query " << XPath << " failed\n";
        std::cerr << e.what() << "\n";
        exit( -1 );
    }
    catch(std::exception &e)
    {
        std::cerr << "Query " << XPath << " failed\n";
        std::cerr << e.what() << "\n";
        exit( -1 );
    }

}

int main(int argc, char **argv)
{

    std::string path2DbEnv;
    std::string theContainer = "simpleExampleData.dbxml";
    for ( int i=1; i<argc; i++ )
    {
        if ( argv[i][0] == '-' )
        {
            switch(argv[i][1])
            {
              case 'h':
                path2DbEnv = argv[++i];
                break;
              default:
                usage();
            }
         }
     }

     if (! path2DbEnv.length() )
        usage();

    //open a container in the db environment
    myDbEnv theDBEnv( path2DbEnv ); 
    myXmlContainer openedContainer( theContainer, theDBEnv );

    //perform the queries

    //find all the Vendor documents in the database
    doQuery( openedContainer.getContainer(), "/vendor" );

    //find all the vendors that are wholesale shops
    doQuery( openedContainer.getContainer(), "/vendor[@type=\"wholesale\"]");

    //find the product document for "Lemon Grass"
    doQuery( openedContainer.getContainer(), "/product/item[text()=\"Lemon Grass\"]");

    //find all the products where the price is less than or equal to 0.11
    doQuery( openedContainer.getContainer(), "/product/inventory[number(price)<=0.11]");
    
    //find all the vegetables where the price is less than or equal to 0.11
    doQuery( openedContainer.getContainer(), "/product[number(inventory/price)<=0.11 and category/text()=\"vegetables\"]");

    return 0;
}
