import os
import socket
import subprocess
import sys
import time

packages = dict()

root = os.path.dirname(os.path.dirname(os.path.dirname(
    os.path.dirname(__file__))))
instances_root = os.path.join(root, 'instances')
instances = dict()
print "ROOT: ", root
for pkg_name in os.listdir(instances_root):
    try:
        if pkg_name.startswith('.') or '.' not in pkg_name:
            continue
        path_ = os.path.join(instances_root, pkg_name)
        if not os.path.isdir(path_):
            continue
        name = pkg_name.split('.')[-1]
        instances[name] = path_
    except:
        # not a package
        pass

print "WAEUP.STRESS.INIT: INSTANCES: ", instances

def enable_datafs(path, proj_name):
    """Copy data.fs in `path` for kofa project `proj_name`.
    """
    pkg = packages[proj_name]
    #src_path = os.path.join(

def bootstrap():
    """Run bootstrap and buildout for each of the KOFA instances
    """
    for name, path in instances.items():
        bootstrap_instance(name, path)
    return

def bootstrap_instance(name, path):
    """Run bootstrap.py and buildout for instance `name` at `path`.
    """
    print "WAEUP.STRESS: bootstrapping %s" % name
    print "WAEUP.STRESS: path: %s" % path
    old_cwd_ = os.getcwd()
    os.chdir(path)
    print "WAEUP.STRESS: bootstrapping %s" % name
    subprocess.call(['python', 'bootstrap/bootstrap.py'])
    print "WAEUP.STRESS: running buildout for %s" % name
    subprocess.call(['./bin/buildout'], shell=True)
    os.chdir(old_cwd_)
    return

def remove_zodb(name):
    path = instances[name]
    print "WAEUP.STRESS: removing ZODB of %s at %s" % (name, path)
    filestorage_dir = os.path.join(path, 'var', 'filestorage')
    for filename in os.listdir(filestorage_dir):
        if filename in ['Data.fs', 'Data.fs.tmp', 'Data.fs.index',
                        'Data.fs.lock']:
            filepath = os.path.join(filestorage_dir,  filename)
            print "  removing %s" % filepath
            os.unlink(filepath)
    return

def start_instance(name, mode='paster'):
    """Start instance `name` in `mode`.

    The `name` should be someone like 'kofa', 'uniben', etc. where
    ``waeup.<NAME>`` is an existent instance in the `instances/`
    directory.

    `mode` can be one of `paster`|`kofactl`|`zeo`|`profile` and tells
    how to start the instance.
    """
    path = instances[name]
    print "WAEUP.STRESS: starting instance %s at %s using %s" % (
        name, path, mode)
    old_cwd_ = os.getcwd()
    os.chdir(path)
    # yes, shell _is_ neccessary here
    if mode == 'kofactl':
        subprocess.call('./bin/kofactl start', shell=True)
    elif mode == 'profile':
        subprocess.call(
            './bin/paster serve --daemon parts/etc/profile.ini', shell=True)
    elif mode == 'zeo':
        os.listdir('./bin')
        subprocess.call('./bin/zeo_server start', shell=True)
        subprocess.call('./bin/zeo_client1 start', shell=True)
        subprocess.call('./bin/zeo_client2 start', shell=True)
    else:
        # by default we start paster as daemon
        subprocess.call(
            './bin/paster serve --daemon parts/etc/deploy.ini', shell=True)
    os.chdir(old_cwd_)
    return

def wait_for_startup(host, port):
    """Wait until a connection to host and port can be made.

    After a timeout of 10 secs we abort raising an IOError.
    """
    print "WAEUP.STRESS.INIT: waiting for instance(s) to come up on %s:%s" % (
        host, port)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    start = time.time()
    while True:
        if time.time() - 10 > start:
            raise IOError('timeout while waiting for instance to come up')
        try:
            s.connect((host, port))
            break
        except:
            time.sleep(0.1)
    s.close()
    print "WAEUP.STRESS.INIT: instance(s) up after %.2f secs" % (
        time.time() - start,)
    return

def stop_instance(name, mode='paster'):
    """Stop instance `name` in `mode`.

    The `name` should be someone like 'kofa', 'uniben', etc. where
    ``waeup.<NAME>`` is an existent instance in the `instances/`
    directory.

    `mode` can be one of `paster`|`kofactl` and tells which tool to
    use to stop the instance.
    """
    path = instances[name]
    print "WAEUP.STRESS: shutting down instance %s at %s using %s" % (
        name, path, mode),
    old_cwd_ = os.getcwd()
    os.chdir(path)
    if mode == 'kofactl':
        subprocess.call('./bin/kofactl stop', shell=True)
    elif mode == 'zeo':
        subprocess.call('./bin/zeo_client2 stop', shell=True)
        subprocess.call('./bin/zeo_client1 stop', shell=True)
        subprocess.call('./bin/zeo_server stop', shell=True)
    else:
        # by default we use paster
        subprocess.call(
        './bin/paster serve --stop-daemon', shell=True)
    print "... done."
    os.chdir(old_cwd_)
    return

def install_app(name):
    """Execute waeup.stress.script in instance context.
    """
    return exec_in_instance(name, 'install_app')
    path = instances[name]
    old_cwd_ = os.getcwd()
    os.chdir(path)
    script = os.path.join(os.path.dirname(__file__), 'scripts.py')
    subprocess.call(
        './bin/python-console %s' % script, shell=True)
    os.chdir(old_cwd_)

def import_csv(name, *paths):
    return exec_in_instance(name, 'import_csv', *paths)

def exec_in_instance(name, cmd, *args):
    path = instances[name]
    old_cwd_ = os.getcwd()
    os.chdir(path)
    script = os.path.join(os.path.dirname(__file__), 'scripts.py')
    if args:
        args = ' '.join(args)
    else:
        args = ''
    subprocess.call(
        './bin/python-console %s %s %s' % (
            script, cmd, args), shell=True)
    os.chdir(old_cwd_)
