#!/usr/bin/env python
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import atexit
import base64
import contextlib
import functools
import glob
import inspect
import json
import ntpath
import optparse
import os
import posixpath
import re
import subprocess as sp
import sys
import time
import uuid

from pbkdf2 import pbkdf2_hex

COMMON_SALT = uuid.uuid4().hex

try:
    from urllib import urlopen
except ImportError:
    from urllib.request import urlopen

try:
    import httplib as httpclient
except ImportError:
    import http.client as httpclient


def toposixpath(path):
    if os.sep == ntpath.sep:
        return path.replace(ntpath.sep, posixpath.sep)
    else:
        return path

def log(msg):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            def print_(chars):
                if log.verbose:
                    sys.stdout.write(chars)
                    sys.stdout.flush()
            callargs = dict(list(zip(inspect.getargspec(func).args, args)))
            callargs.update(kwargs)
            print_('[ * ] ' + msg.format(**callargs) + ' ... ')
            try:
                res = func(*args, **kwargs)
            except KeyboardInterrupt:
                print_('ok\n')
            except Exception as err:
                print_('failed: %s\n' % err)
                raise
            else:
                print_('ok\n')
                return res
        return wrapper
    return decorator
log.verbose = True


def main():
    ctx = setup()
    startup(ctx)
    if ctx['cmd']:
        run_command(ctx, ctx['cmd'])
    else:
        join(ctx, 15984, *ctx['admin'])


def setup():
    opts, args = setup_argparse()
    ctx = setup_context(opts, args)
    setup_logging(ctx)
    setup_dirs(ctx)
    check_beams(ctx)
    setup_configs(ctx)
    return ctx


def setup_logging(ctx):
    log.verbose = ctx['verbose']


def setup_argparse():
    parser = optparse.OptionParser(description='Runs CouchDB 2.0 dev cluster')
    parser.add_option('-a', '--admin', metavar='USER:PASS', default=None,
                      help="Add an admin account to the development cluster")
    parser.add_option("-n", "--nodes", metavar="nodes", default=3,
                      type=int,
                      help="Number of development nodes to be spun up")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose", default=True,
                      help="Don't print anything to STDOUT")
    parser.add_option('--with-admin-party-please',
                      dest='with_admin_party', default=False,
                      action='store_true',
                      help='Runs a dev cluster with admin party mode on')
    parser.add_option('--enable-erlang-views',
                      action='store_true',
                      help='Enables the Erlang view server')
    parser.add_option('--no-join',
                      dest='no_join', default=False,
                      action='store_true',
                      help='Do not join nodes on boot')
    parser.add_option('--with-haproxy', dest='with_haproxy', default=False,
                      action='store_true', help='Use HAProxy')
    parser.add_option('--haproxy', dest='haproxy', default='haproxy',
                      help='HAProxy executable path')
    parser.add_option('--haproxy-port', dest='haproxy_port', default='5984',
                      help='HAProxy port')
    parser.add_option('--node-number', dest="node_number", type=int, default=1,
                      help='The node number to seed them when creating the node(s)')
    parser.add_option('-c', '--config-overrides', action="append", default=[],
                      help='Optional key=val config overrides. Can be repeated')
    return parser.parse_args()


def setup_context(opts, args):
    fpath = os.path.abspath(__file__)
    return {'N': opts.nodes,
            'no_join': opts.no_join,
            'with_admin_party': opts.with_admin_party,
            'enable_erlang_views': opts.enable_erlang_views,
            'admin': opts.admin.split(':', 1) if opts.admin else None,
            'nodes': ['node%d' % (i + opts.node_number) for i in range(opts.nodes)],
            'node_number': opts.node_number,
            'devdir': os.path.dirname(fpath),
            'rootdir': os.path.dirname(os.path.dirname(fpath)),
            'cmd': ' '.join(args),
            'verbose': opts.verbose,
            'with_haproxy': opts.with_haproxy,
            'haproxy': opts.haproxy,
            'haproxy_port': opts.haproxy_port,
            'config_overrides': opts.config_overrides,
            'reset_logs': True,
            'procs': []}


@log('Setup environment')
def setup_dirs(ctx):
    ensure_dir_exists(ctx['devdir'], 'data')
    ensure_dir_exists(ctx['devdir'], 'logs')


def ensure_dir_exists(root, *segments):
    path = os.path.join(root, *segments)
    if not os.path.exists(path):
        os.makedirs(path)
    return path


@log('Ensure CouchDB is built')
def check_beams(ctx):
    for fname in glob.glob(os.path.join(ctx['devdir'], "*.erl")):
        sp.check_call(["erlc", "-o", ctx['devdir'] + os.sep, fname])


@log('Prepare configuration files')
def setup_configs(ctx):
    if os.path.exists("src/fauxton/dist/release"):
        fauxton_root = "src/fauxton/dist/release"
    else:
        fauxton_root = "share/www"

    for idx, node in enumerate(ctx['nodes']):
        cluster_port, backend_port = get_ports(idx + ctx['node_number'])
        env = {
            "prefix": toposixpath(ctx['rootdir']),
            "package_author_name": "The Apache Software Foundation",
            "data_dir": toposixpath(ensure_dir_exists(ctx['devdir'],
                                          "lib", node, "data")),
            "view_index_dir": toposixpath(ensure_dir_exists(ctx['devdir'],
                                                "lib", node, "data")),
            "node_name": "-name %s@127.0.0.1" % node,
            "cluster_port": cluster_port,
            "backend_port": backend_port,
            "fauxton_root": fauxton_root,
            "uuid": "fake_uuid_for_dev",
            "_default": "",
            "compaction_daemon": "{}"
        }
        write_config(ctx, node, env)


def apply_config_overrides(ctx, content):
    for kv_str in  ctx['config_overrides']:
        key, val = kv_str.split('=')
        key, val = key.strip(), val.strip()
        match = "[;=]{0,2}%s.*" % key
        repl = "%s = %s" % (key, val)
        content = re.sub(match, repl, content)
    return content


def get_ports(idnode):
    assert idnode
    return ((10000 * idnode) + 5984, (10000 * idnode) + 5986)


def write_config(ctx, node, env):
    etc_src = os.path.join(ctx['rootdir'], "rel", "overlay", "etc")
    etc_tgt = ensure_dir_exists(ctx['devdir'], "lib", node, "etc")

    for fname in glob.glob(os.path.join(etc_src, "*")):
        base = os.path.basename(fname)
        tgt = os.path.join(etc_tgt, base)

        if os.path.isdir(fname):
            continue

        with open(fname) as handle:
            content = handle.read()

        for key in env:
            content = re.sub("{{%s}}" % key, str(env[key]), content)

        if base == "default.ini":
            content = hack_default_ini(ctx, node, content)
            content = apply_config_overrides(ctx, content)
        elif base == "local.ini":
            content = hack_local_ini(ctx, content)

        with open(tgt, "w") as handle:
            handle.write(content)


def boot_haproxy(ctx):
    if not ctx['with_haproxy']:
        return
    config = os.path.join(ctx['rootdir'], "rel", "haproxy.cfg")
    cmd = [
        ctx['haproxy'],
        "-f",
        config
    ]
    logfname = os.path.join(ctx['devdir'], "logs", "haproxy.log")
    log = open(logfname, "w")
    env = os.environ.copy()
    if "HAPROXY_PORT" not in env:
        env["HAPROXY_PORT"] = ctx['haproxy_port']
    return sp.Popen(
            " ".join(cmd),
            shell=True,
            stdin=sp.PIPE,
            stdout=log,
            stderr=sp.STDOUT,
            env=env
        )


def hack_default_ini(ctx, node, contents):
    # Replace couchjs command
    couchjs = os.path.join(ctx['rootdir'], "src", "couch", "priv", "couchjs")
    mainjs = os.path.join(ctx['rootdir'], "share", "server", "main.js")
    coffeejs = os.path.join(ctx['rootdir'], "share", "server", "main-coffee.js")

    repl = toposixpath("javascript = %s %s" % (couchjs, mainjs))
    contents = re.sub("(?m)^javascript.*$", repl, contents)

    repl = toposixpath("coffeescript = %s %s" % (couchjs, coffeejs))
    contents = re.sub("(?m)^coffeescript.*$", repl, contents)

    if ctx['enable_erlang_views']:
        contents = re.sub(
            "^\[native_query_servers\]$",
            "[native_query_servers]\nerlang = {couch_native_process, start_link, []}",
            contents,
            flags=re.MULTILINE)

    return contents


def hack_local_ini(ctx, contents):
    # make sure all three nodes have the same secret
    secret_line = "secret = %s\n" % COMMON_SALT
    previous_line = "; require_valid_user = false\n"
    contents = contents.replace(previous_line, previous_line + secret_line)

    if ctx['with_admin_party']:
        ctx['admin'] = ('Admin Party!', 'You do not need any password.')
        return contents

    # handle admin credentials passed from cli or generate own one
    if ctx['admin'] is None:
        ctx['admin'] = user, pswd = 'root', gen_password()
    else:
        user, pswd = ctx['admin']

    return contents + "\n%s = %s" % (user, hashify(pswd))


def gen_password():
    # TODO: figure how to generate something more friendly here
    return base64.b64encode(os.urandom(6)).decode()


def hashify(pwd, salt=COMMON_SALT, iterations=10, keylen=20):
    """
    Implements password hashing according to:
      - https://issues.apache.org/jira/browse/COUCHDB-1060
      - https://issues.apache.org/jira/secure/attachment/12492631/0001-Integrate-PBKDF2.patch

    This test uses 'candeira:candeira'

    >>> hashify(candeira)
    -pbkdf2-99eb34d97cdaa581e6ba7b5386e112c265c5c670,d1d2d4d8909c82c81b6c8184429a0739,10
    """
    derived_key = pbkdf2_hex(pwd, salt, iterations, keylen)
    return "-pbkdf2-%s,%s,%s" % (derived_key, salt, iterations)


def startup(ctx):
    atexit.register(kill_processes, ctx)
    boot_nodes(ctx)
    ensure_all_nodes_alive(ctx)
    if ctx['no_join']:
        return
    if ctx['with_admin_party']:
        cluster_setup_with_admin_party(ctx)
    else:
        cluster_setup(ctx)


def kill_processes(ctx):
    for proc in ctx['procs']:
        if proc and proc.returncode is None:
            proc.kill()


def boot_nodes(ctx):
    for node in ctx['nodes']:
        ctx['procs'].append(boot_node(ctx, node))
    ctx['procs'].append(boot_haproxy(ctx))


def ensure_all_nodes_alive(ctx):
    status = dict((num, False) for num in range(ctx['N']))
    for _ in range(10):
        for num in range(ctx['N']):
            if status[num]:
                continue
            local_port, _ = get_ports(num + ctx['node_number'])
            url = "http://127.0.0.1:{0}/".format(local_port)
            try:
                check_node_alive(url)
            except:
                pass
            else:
                status[num] = True
        if all(status.values()):
            return
        time.sleep(1)
    if not all(status.values()):
        print('Failed to start all the nodes.'
              ' Check the dev/logs/*.log for errors.')
        sys.exit(1)


@log('Check node at {url}')
def check_node_alive(url):
    error = None
    for _ in range(10):
        try:
            with contextlib.closing(urlopen(url)):
                pass
        except Exception as exc:
            error = exc
            time.sleep(1)
        else:
            error = None
            break
    if error is not None:
        raise error


@log('Start node {node}')
def boot_node(ctx, node):
    erl_libs = os.path.join(ctx['rootdir'], "src")
    env = os.environ.copy()
    env["ERL_LIBS"] = os.pathsep.join([erl_libs])

    node_etcdir = os.path.join(ctx['devdir'], "lib", node, "etc")
    reldir = os.path.join(ctx['rootdir'], "rel")
    cmd = [
        "erl",
        "-args_file", os.path.join(node_etcdir, "vm.args"),
        "-config", os.path.join(reldir, "files", "sys"),
        "-couch_ini",
        os.path.join(node_etcdir, "default.ini"),
        os.path.join(node_etcdir, "local.ini"),
        "-reltool_config", os.path.join(reldir, "reltool.config"),
        "-parent_pid", str(os.getpid()),
        "-pa", ctx['devdir'],
        "-pa", os.path.join(erl_libs, "*"),
        "-s", "boot_node"
    ]
    if ctx['reset_logs']:
        mode = "wb"
    else:
        mode = "r+b"
    logfname = os.path.join(ctx['devdir'], "logs", "%s.log" % node)
    log = open(logfname, mode)
    cmd = [toposixpath(x) for x in cmd]
    return sp.Popen(cmd, stdin=sp.PIPE, stdout=log, stderr=sp.STDOUT, env=env)


@log('Running cluster setup')
def cluster_setup(ctx):
    lead_port, _ = get_ports(1)
    if enable_cluster(ctx['N'], lead_port, *ctx['admin']):
        for num in range(1, ctx['N']):
            node_port, _ = get_ports(num + 1)
            enable_cluster(ctx['N'], node_port, *ctx['admin'])
            add_node(lead_port, node_port, *ctx['admin'])
        finish_cluster(lead_port, *ctx['admin'])
    return lead_port


def enable_cluster(node_count, port, user, pswd):
    conn = httpclient.HTTPConnection('127.0.0.1', port)
    conn.request('POST', '/_cluster_setup',
                 json.dumps({'action': 'enable_cluster',
                             'bind_address': '0.0.0.0',
                             'username': user,
                             'password': pswd,
                             'node_count': node_count}),
                 {'Authorization': basic_auth_header(user, pswd),
                  'Content-Type': 'application/json'})
    resp = conn.getresponse()
    if resp.status == 400:
        resp.close()
        return False
    assert resp.status == 201, resp.read()
    resp.close()
    return True


def add_node(lead_port, node_port, user, pswd):
    conn = httpclient.HTTPConnection('127.0.0.1', lead_port)
    conn.request('POST', '/_cluster_setup',
                 json.dumps({'action': 'add_node',
                             'host': '127.0.0.1',
                             'port': node_port,
                             'username': user,
                             'password': pswd}),
                 {'Authorization': basic_auth_header(user, pswd),
                  'Content-Type': 'application/json'})
    resp = conn.getresponse()
    assert resp.status in (201, 409), resp.read()
    resp.close()


def set_cookie(port, user, pswd):
    conn = httpclient.HTTPConnection('127.0.0.1', port)
    conn.request('POST', '/_cluster_setup',
                 json.dumps({'action': 'receive_cookie',
                             'cookie': generate_cookie()}),
                 {'Authorization': basic_auth_header(user, pswd),
                  'Content-Type': 'application/json'})
    resp = conn.getresponse()
    assert resp.status == 201, resp.read()
    resp.close()


def finish_cluster(port, user, pswd):
    conn = httpclient.HTTPConnection('127.0.0.1', port)
    conn.request('POST', '/_cluster_setup',
                 json.dumps({'action': 'finish_cluster'}),
                 {'Authorization': basic_auth_header(user, pswd),
                  'Content-Type': 'application/json'})
    resp = conn.getresponse()
    # 400 for already set up'ed cluster
    assert resp.status in (201, 400), resp.read()
    resp.close()


def basic_auth_header(user, pswd):
    return 'Basic ' + base64.b64encode((user + ':' + pswd).encode()).decode()


def generate_cookie():
    return base64.b64encode(os.urandom(12)).decode()


def cluster_setup_with_admin_party(ctx):
    host, port = '127.0.0.1', 15986
    for node in ctx['nodes']:
        body = '{}'
        conn = httpclient.HTTPConnection(host, port)
        conn.request('PUT', "/_nodes/%s@127.0.0.1" % node, body)
        resp = conn.getresponse()
        if resp.status not in (200, 201, 202, 409):
            print(('Failed to join %s into cluster: %s' % (node, resp.read())))
            sys.exit(1)
    create_system_databases(host, 15984)


def try_request(host, port, meth, path, success_codes, retries=10, retry_dt=1):
    while True:
        conn = httpclient.HTTPConnection(host, port)
        conn.request(meth, path)
        resp = conn.getresponse()
        if resp.status in success_codes:
            return resp.status, resp.read()
        elif retries <= 0:
            assert resp.status in success_codes, resp.read()
        retries -= 1
        time.sleep(retry_dt)


def create_system_databases(host, port):
    for dbname in ['_users', '_replicator', '_global_changes']:
        conn = httpclient.HTTPConnection(host, port)
        conn.request('HEAD', '/' + dbname)
        resp = conn.getresponse()
        if resp.status == 404:
            try_request(host, port, 'PUT', '/' + dbname, (201, 202, 412))


@log('Developers cluster is set up at http://127.0.0.1:{lead_port}.\n'
     'Admin username: {user}\n'
     'Password: {password}\n'
     'Time to hack!')
def join(ctx, lead_port, user, password):
    while True:
        for proc in ctx['procs']:
            if proc is not None and proc.returncode is not None:
                exit(1)
        time.sleep(2)


@log('Exec command {cmd}')
def run_command(ctx, cmd):
    p = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sys.stderr)
    while True:
        line = p.stdout.readline()
        if not line:
            break
        eval(line)
    p.wait()
    exit(p.returncode)


@log('Restart all nodes')
def reboot_nodes(ctx):
    ctx['reset_logs'] = False
    kill_processes(ctx)
    boot_nodes(ctx)
    ensure_all_nodes_alive(ctx)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass
