#!/usr/bin/env python

# ============================================================================
#
#                               Preamble
#
# ============================================================================


from optparse import OptionParser
import sqlite3
import sys
import os
import time

from glue.ligolw import lsctables
from glue.ligolw import dbtables
from glue.ligolw.utils import process
from glue import git_version

from pylal import ligolw_sqlutils as sqlutils

__prog__ = "ligolw_cbc_dbsimplify"
__author__ = "Collin Capano <cdcapano@physics.syr.edu>"

description = \
"Cleans and simplifies a database by removing redundant ids."

# ============================================================================
#
#                               Set Options
#
# ============================================================================

def parse_command_line():
    """
    Parser function dedicated
    """
    parser = OptionParser(
        version = git_version.verbose_msg,
        usage   = "%prog [options]",
        description = description
        )
    # following are related to file input and output naming
    parser.add_option( "-d", "--database", action = "store", type = "string", default = None,
        help =
            "Database to update. Must already exist."
            )
    parser.add_option( "-t", "--tmp-space", action = "store", type = "string", default = None,
        metavar = "PATH",
        help =
            "Location of local disk on which to do work. This is optional; " +
            "it is only used to enhance performance in a networked " +
            "environment. "
            )
    parser.add_option( "", "--vacuum", action = "store_true", default = False,
        help = 
            "If turned on, will vacuum the database before saving. " +
            "This cleans any fragmentation and removes empty space " +
            "left behind by all the DELETEs, making the output " +
            "database smaller and more efficient. " +
            "WARNING: Since this requires rebuilding the entire " +
            "database, this can take awhile for larger files." 
            )

    parser.add_option( "-v", "--verbose", action = "store_true", default = False,
        help =
            "Print progress information"
           )
    parser.add_option( "-D", "--debug", action = "store_true", default = False,
        help =
            "Print SQLite queries used and the approximate time taken to run each one." )

    (options, args) = parser.parse_args()
    # check for required options and for self-consistency
    if not options.database:
        raise ValueError, "No database specified."

    return options, sys.argv[1:]


# =============================================================================
#
#                                     Main
#
# =============================================================================

opts, args = parse_command_line()

# get input database filename
filename = opts.database
if not os.path.isfile( filename ):
    raise ValueError, "The input file, %s, cannot be found." % filename

# Setup working databases and connections
if opts.verbose: 
    print >> sys.stdout, "Creating a database connection..."
working_filename = dbtables.get_connection_filename( 
    filename, tmp_path = opts.tmp_space, verbose = opts.verbose )
connection = sqlite3.connect( working_filename )
if opts.tmp_space:
    dbtables.set_temp_store_directory(connection, opts.tmp_space, verbose = opts.verbose)

# Add program to process and process params table

# FIXME: remove the following two lines once boolean type
# has been properly handled
from glue.ligolw import types as ligolwtypes
ligolwtypes.FromPyType[type(True)] = ligolwtypes.FromPyType[type(8)]

xmldoc = dbtables.get_xml(connection)
proc_id = process.register_to_xmldoc(xmldoc, 'ligolw_cbc_dbsimplify', opts.__dict__, version = git_version.id)

# Cleaning up the veto_definer and segments tables
sqlutils.simplify_segments_tbls(connection, verbose=opts.verbose, debug=opts.debug)
sqlutils.simplify_vetodef_tbl(connection, verbose=opts.verbose, debug=opts.debug)

# Make process_id map from info in the process & process_params tables
sqlutils.get_process_info(connection, verbose=opts.verbose, debug=opts.debug)

sqlutils.simplify_timeslide_tbl(connection, verbose=opts.verbose, debug=opts.debug)
sqlutils.simplify_sim_tbls(connection, verbose=opts.verbose, debug=opts.debug)
# Remove empty space & defragment database
sqlutils.vacuum_database(connection, vacuum=opts.vacuum, verbose=opts.verbose)

# Cleaning up the coinc_definer & experiment tables
sqlutils.simplify_coincdef_tbl(connection, verbose=opts.verbose, debug=opts.debug)
sqlutils.simplify_expr_tbl(connection, verbose=opts.verbose, debug=opts.debug)
sqlutils.simplify_exprsumm_tbl(connection, verbose=opts.verbose, debug=opts.debug)

# Cleaning up the summary tables
sqlutils.simplify_summ_tbls(connection, verbose=opts.verbose, debug=opts.debug)
# Update process_ids in the sngl-ifo trigger tables tables
sqlutils.update_pid_in_snglstbls(connection, verbose=opts.verbose, debug=opts.debug)
# Cleaning up the process & process_params tables
sqlutils.simplify_proc_tbls(connection, verbose=opts.verbose, debug=opts.debug)

# Remove empty space & defragment database
sqlutils.vacuum_database(connection, vacuum=opts.vacuum, verbose=opts.verbose)

#
#       Save and Exit
#

connection.commit()
connection.close()

# write output database
dbtables.put_connection_filename(filename, working_filename, verbose = opts.verbose)

if opts.verbose:
    print >> sys.stdout, "Program Finished!"

# set process end time
process.set_process_end_time(proc_id)
sys.exit(0)

