#!/usr/bin/env python
# vim: set shiftwidth=4 softtabstop=4:
"""Script to run test with local modules
"""
# Version 2.15
import argparse
import json
import logging
import os
import signal
from subprocess import call
import sys

import ConfigParser

import docker  # apt python-docker (1.9) or pip install docker

# local file
import docker_dev_start

if docker.__version__ > '3.0.0':
    from docker import APIClient as docker_api
else:
    from docker import Client as docker_api

_logger = logging.getLogger(__name__)

__version__ = '0.0.1'
__date__ = '2018-04-13'
__updated__ = '2018-04-13'


def main(argv=None):  # IGNORE:C0111
    """Parse arguments and docker build
    """
    program_version = __version__
    program_build_date = str(__updated__)
    program_version_message = '%%(prog)s %s (%s)' % (
        program_version, program_build_date)
    program_shortdesc = __doc__.split(".")[0]
    program_license = '''%s

  Created by Vincent Hatakeyama on %s.
  Copyright 2018 XCG Consulting. All rights reserved.

  Licensed under the MIT License

  Distributed on an "AS IS" basis without warranties
  or conditions of any kind, either express or implied.

USAGE
''' % (program_shortdesc, str(__date__))

    # TODO the script assume it is launched from the parent super project
    project_path = os.path.realpath('.')
    project_name = os.path.basename(project_path)
    if project_name == 'odoo_scripts':
        logging.fatal(
            "You must run this script from the super project"
            " (./odoo_scripts/docker_build.py)")
        return 1

    setup_path = 'setup.cfg'
    # TODO add a way to store configuration options in a project file
    # Argument parsing
    parser = argparse.ArgumentParser(
        description=program_license,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        '-V', '--version', action='version',
        version=program_version_message)
    parser.add_argument(
        '-v', '--verbose', dest='verbose', action='count',
        help="set verbosity level [default: %(default)s]")
    docker_group = parser.add_mutually_exclusive_group()
    docker_group.add_argument(
        '--docker',
        help="Use docker to launch tests",
        action='store_true',
        default=True,
        dest='docker',
    )
    docker_group.add_argument(
        '--no-docker',
        help="Do not use docker to launch tests",
        action='store_false',
        dest='docker',
    )
    parser.add_argument(
        '-d',
        '--dbname',
        help="Database name [default: %(default)s]",
        default='%s_test' % project_name,
    )
    parser.add_argument(
        '--db_user',
        help="Odoo database user [default: %(default)s]",
        default=None,
    )
    parser.add_argument(
        '--db_password',
        help="Odoo database password [default: %(default)s]",
        default=None,
    )
    # TODO options
    # - db host/uri (include socket)
    # - db user for creation/remove
    # - odoo log level
    # - create db

    nmspc = parser.parse_args(argv)
    verbose = nmspc.verbose
    if not verbose:
        logging.basicConfig(level=logging.WARN)
    if verbose == 1:
        logging.basicConfig(level=logging.INFO)
    if verbose and verbose > 1:
        logging.basicConfig(level=logging.DEBUG)
    dbname = nmspc.dbname
    odoo_db_user = nmspc.db_user
    odoo_db_password = nmspc.db_password
    recreate_db = True
    extensions = []
    install_log_level = None
    test_log_level = None

    # Get parameters from setup file

    c = ConfigParser.ConfigParser()
    if not os.path.exists(setup_path):
        logging.fatal('Missing %s', setup_path)
        return 12
    c.read(setup_path)

    if c.has_option('odoo_scripts', 'addon_dirs'):
        addon_dirs = c.get('odoo_scripts', 'addon_dirs', '').split()
    else:
        addon_dirs = ''
    logging.debug("addon directories: %s", addon_dirs)

    registry = (
        c.has_section('odoo_scripts') and
        c.has_option('odoo_scripts', 'registry') and
        c.get('odoo_scripts', 'registry')) or 'dockerhub.xcg.io'
    project = (
        c.has_section('odoo_scripts') and
        c.has_option('odoo_scripts', 'image') and
        c.get('odoo_scripts', 'image')) or os.path.basename(project_path)
    odoo_type = (
        c.has_section('odoo_scripts') and
        c.has_option('odoo_scripts', 'odoo_type') and
        c.get('odoo_scripts', 'odoo_type')) or 'odoo7'
    image = "%s/%s:latest" % (registry, project)
    logging.debug("Docker image: %s", image)

    # read from odoo.conf if it exists
    sample_conf = 'conf/dev/odoo.conf'
    if os.path.exists(sample_conf):
        logging.info('Reading from sample configuration %s', sample_conf)
        c.read(sample_conf)
        if not odoo_db_user:
            odoo_db_user = c.get('options', 'db_user')
        if (
            c.has_option('options', 'unaccent') and
            c.getboolean('options', 'unaccent')
        ):
            extensions.append('unaccent')
    else:
        logging.debug('No sample configuration %s', sample_conf)
        extensions.append('unaccent')

    # Do stuff

    if nmspc.docker:
        # TODO detect that user is member of docker group
        args = [
            '-d',
            dbname,
            '--stop-after-init',
            '--max-cron-threads',
            '0',
            '--no-flake8',
            '--no-dev',
        ]
        if odoo_db_user:
            args.append('--db_user')
            args.append(odoo_db_user)
        else:
            # TODO find from odoo version and conf file
            pass
        if odoo_db_password:
            args.append('--db_password')
            args.append(odoo_db_password)

    docker_dev_start.flake8()
    if recreate_db:
        # XXX use psycopg2
        # drop database
        logging.info("Drop any existing database %s", dbname)
        result = call(['dropdb', dbname, '--if-exists', '--no-password'])
        if result:
            return result
        # create database
        logging.info("Create database %s", dbname)
        if not odoo_db_user:
            logging.fatal(
                'Owner of database is mandatory when creating database')
            return 14
        result = call(['createdb', dbname, '-O', odoo_db_user, '--no-password'])
        if result:
            return result
        # add unaccent if needed
        for extension in extensions:
            logging.info("Adding extension %s", extension)
            result = call([
                'psql', dbname, '-c', 'CREATE EXTENSION %s;' % extension])
            if result:
                return result

        # TODO start odoo and detect if install fails
        if nmspc.docker:
            install_args = list(args)
            install_args.append('--install-default')
            if install_log_level:
                install_args.append('--log-level=%s' % install_log_level)
            docker_dev_start.main(install_args)

            if result:
                return result
        else:
            raise NotImplementedError
    # TODO start odoo and detect if test fails
    if nmspc.docker:
        test_args = list(args)
        test_args.append('--test-default')
        if test_log_level:
            install_args.append('--log-level=%s' % test_log_level)
        return docker_dev_start.main(test_args)
    else:
        raise NotImplementedError
    return 255


if __name__ == "__main__":
    return_code = main(sys.argv[1:])
    if return_code:
        exit(return_code)