#!/usr/bin/env python

"""
Copy/append a collection to another collection.

Can be used to copy the contents of one or more collections to another 
collection.  Assumes the same mongodb server, but can work across multiple 
databases.
"""

import os
import sys

from optparse import OptionParser

import pymongo
from pymongo.errors import ConnectionFailure

class ConnectionException(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def _connection(host, db_name, user, password):
    try:
        conn = pymongo.Connection(host=host)
    except ConnectionFailure:
        raise ConnectionException("Couldn't connect to DB "
                            "at {host}".format(host=host))

    db = conn[db_name]

    if user:
        success = db.authenticate(user, password)
        if not success:
            raise ConnectionException("Could not authenticate to "
                    "database {db} as user {user}".format(user=user, db=db_name))

    return db


def main():
    usage = '%prog [ -S source_db | -T target_db | -s source_db | -t target_collection | -h host | -u user | -p pass]'
    parser = OptionParser(usage=usage)
    parser.add_option('-S', '--source_db', metavar='SOURCE_DB',
            type='string', dest='source_db', 
            help='Source mongo database.')
    parser.add_option('-T', '--target_db', metavar='TARGET_DB',
            type='string', dest='target_db', 
            help='Target mongo database.')
    parser.add_option('-s', '--source_collection', metavar='SOURCE_COLLECTION',
            type='string', dest='source_collection', 
            help='Source collection.')
    parser.add_option('-t', '--target_collection', metavar='TARGET_COLLECTION',
            type='string', dest='target_collection', 
            help='Target collection.')
    parser.add_option('-H', '--host', metavar='HOST',
            type='string', dest='host', default='localhost',
            help='Mongo hostname (default localhost).')
    parser.add_option('-u', '--user', metavar='USER',
            type='string', dest='user', 
            help='Mongo username.')
    parser.add_option('-p', '--password', metavar='PASSWORD',
            type='string', dest='password', 
            help='Mongo password.')
    options, args = parser.parse_args()

    for arg in ['source_db', 'target_db', 'source_collection', 'target_collection']:
        if not getattr(options, '{0}'.format(arg)):
            parser.error('All source/target args required.')

    source_db = _connection(options.host, options.source_db, options.user, options.password)
    target_db = _connection(options.host, options.target_db, options.user, options.password)

    source_collection = source_db[options.source_collection]
    target_collection = target_db[options.target_collection]

    prompt = raw_input('Copy/append source\n {source}\nTo target\n {target}?\n[y/n] : '.format(
        source=source_collection, target=target_collection))
    
    if prompt.lower() == 'y':
        print 'Commencing copy/append...'
        ret = source_collection.find({})

        for doc in ret:
            target_collection.insert(doc)


    

if __name__ == '__main__':
    main()