#include <fstream>
#include <cstdio>

#include "myDbEnv.hpp"
#include "myXmlContainer.hpp"
using namespace DbXml;

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

                  <<  "\t-h <dbenv directory>\n"

                  <<    "Also, for best results run addIndex before running this program.\n" << std::endl;
        exit( -1 );
}


void deleteIndex( XmlContainer &container, const std::string &URI, 
                  const std::string &nodeName, const std::string &indexType,
                  DbTxn *txnid )
{
    std::cout << "Deleting index type: '" << indexType << ""
              << " from node: '" << nodeName << "'." << std::endl;
    try
    {
        //Retrieve the XmlIndexSpecification from the container
        XmlIndexSpecification idxSpec = container.getIndexSpecification( txnid );

        std::cout << "Before the delete, the following indexes are maintained for the container:" << std::endl;
        std::string uri, name, index;
        while( idxSpec.next(uri, name, index) )
        {
            // Obtain the value as a string and print it to the console
            std::cout << "\tFor node '" << name << "', found index: '" << index << "'." << std::endl;
        }
        std::cout << "\n" << std::endl;


        //Delete the indexes from the specification.
        idxSpec.deleteIndex( URI, nodeName, indexType );


        //Set the specification back to the container
        container.setIndexSpecification( txnid, idxSpec );

        //Show the remaining indexes in the container, if any.
        std::cout << "After the delete, the following indexes exist for the container:" << std::endl;
        idxSpec.reset();
        while( idxSpec.next(uri, name, index) )
        {
            // Obtain the value as a string and print it to the console
            std::cout << "\tFor node '" << name << "', found index: '" << index << "'." << std::endl;
        }
        std::cout << "\n" << std::endl;
    }
    //Catches XmlException.
    catch(std::exception &e)
    {
        std::cerr << "Index delete failed: \n";
        std::cerr << e.what() << "\n";

        //Abort the transaction. All changes made to the database since the start
        //of this transaction are discarded.
        txnid->abort();

        exit( -1 );
    }
    std::cout << "Index deleted successfully.\n" << std::endl;
    
}

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

    std::string path2DbEnv;
    std::string theContainer = "namespaceExampleData.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 the environment and the container
    myDbEnv theDBEnv( path2DbEnv ); 
    myXmlContainer openedContainer( theContainer, theDBEnv );

    //myDbEnv and myXmlContainer open with transactions. All subsequent
    //writes to them must also be performed inside a transaction.

    //Get a transaction
    DbTxn *txn;
    theDBEnv.getDbEnv().txn_begin(0, &txn, 0);

    //add an string equality index for the "product" element node.
    deleteIndex( openedContainer.getContainer(), "", "product", "node-element-equality-string", txn );

    //Do these deletes in two different transactions
    // for no particular reason.
    txn->commit( 0 );
    theDBEnv.getDbEnv().txn_begin(0, &txn, 0);

    //add an edge presence index for the product node
    deleteIndex( openedContainer.getContainer(), "", "product", "edge-element-presence-none", txn );

    txn->commit( 0 );

    return 0;


}

