#!/usr/bin/env python3

# Copyright (C) 2020 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
import os
import subprocess
import sys
import time
import threading

sys.dont_write_bytecode = True

from model.docker import Docker
from multiprocessing import Process
from redis import StrictRedis


class DockerIfNeededContext(object):

    def __init__(self, args):
        self.docker = Docker.instance() if 'localhost' in [args.cassandra_server, args.redis_server] else None

    def __enter__(self):
        if self.docker:
            self.docker.__enter__()

    def __exit__(self, *args, **kwargs):
        if self.docker:
            self.docker.__exit__(*args, **kwargs)


def has_gunicorn():
    return not subprocess.run(['python3', '/usr/local/bin/gunicorns', '--version'], capture_output=True).returncode


def parse_arguments():
    parser = argparse.ArgumentParser(description='Run a simple instance of the results database for local development')
    parser.add_argument(
        '--local-cassandra', help='Use a local Cassandra instance',
        dest='cassandra_server', action='store_const', const='localhost',
    )
    parser.add_argument(
        '--mock-cassandra', help='Use a mock Cassandra instance',
        dest='cassandra_server', action='store_const', const='mock',
    )
    parser.set_defaults(cassandra_server='localhost' if Docker.installed() else 'mock')

    parser.add_argument(
        '--local-redis', help='Use a local Redis instance',
        dest='redis_server', action='store_const', const='localhost',
    )
    parser.add_argument(
        '--mock-redis', help='Use a mock Redis instance',
        dest='redis_server', action='store_const', const='mock',
    )
    parser.set_defaults(redis_server='localhost' if Docker.installed() else 'mock')

    parser.add_argument(
        '--drop-keyspace', help='Drop the existing keyspace before running the program',
        dest='drop_keyspace', action='store_true',
    )
    parser.add_argument(
        '--no-drop-keyspace', help='Do NOT drop the existing keyspace before running the program',
        dest='drop_keyspace', action='store_false',
    )
    parser.set_defaults(drop_keyspace=False)

    parser.add_argument(
        '--clear-redis', help='Clear redis before running the application',
        dest='clear_redis', action='store_true',
    )
    parser.add_argument(
        '--no-clear-redis',
        help='Do not clear redis before running the application',
        dest='clear_redis', action='store_false',
    )
    parser.set_defaults(clear_redis=True)

    parser.add_argument(
        '--gunicorn', help='Use the gunicorn webserver',
        dest='gunicorn', action='store_true',
    )
    parser.add_argument(
        '--no-gunicorn',
        help='Do not use the gunicorn webserver',
        dest='gunicorn', action='store_false',
    )
    parser.set_defaults(gunicorn=has_gunicorn())

    return parser.parse_args()


def do_work():
    from example.worker import main
    main()


def web_app():
    from example.main import main
    return main()


def gunicorn():
    if not has_gunicorn():
        print('gunicorn is not installed, please run `pip3 install gunicorn`')
        return 1

    # Slight delay so that the worker is started before the webserver
    time.sleep(2)
    return subprocess.run([
        'python3', '/usr/local/bin/gunicorn',
        'example.main:app',
        '--log-file=-', '--reload',
    ]).returncode


def main():
    args = parse_arguments()
    with DockerIfNeededContext(args):
        os.environ['CASSANDRA_SERVER'] = args.cassandra_server
        os.environ['REDIS_HOST'] = args.redis_server
        os.environ['DROP_KEYSPACE'] = '1' if args.drop_keyspace else '0'
        os.environ['CREATE_KEYSPACE'] = '1'  # Unconditionally create keyspace for testing

        if args.clear_redis and args.redis_server != 'mock':
            StrictRedis(host=args.redis_server).flushdb()

        if args.gunicorn:
            if 'mock' in [args.redis_server, args.cassandra_server]:
                raise RuntimeError('Cannot run with gunicorn and mock databases, asynchronous workers rely on the real databases')

        from example.environment import main as environment_main
        environment_main()

        if not args.gunicorn:
            worker = threading.Thread(target=do_work)
            worker.daemon = True
            worker.start()

            return web_app()

        worker = Process(target=do_work)
        worker.start()

        try:
            return gunicorn()
        finally:
            worker.terminate()
            worker.join()

if __name__ == '__main__':
    sys.exit(main())
