# -*- coding: utf-8; -*-
"""
Development Tasks for Theo
"""

import os
import configparser
import shutil
import sys

from invoke import task
from sphinx.util.console import bold
from sphinx.cmd.quickstart import do_prompt

from bootstrap import inside_virtualenv


here = os.path.abspath(os.path.dirname(__file__))


@task
def bootstrap(c):
    """
    Bootstrap a development environment.
    """
    if not inside_virtualenv():
        sys.exit(1)

    envdir = sys.prefix
    upgrade_pip(c)
    install_app_package(c)
    appdir = make_appdir(c, envdir)

    info = collect_info()
    make_configs(c, envdir, appdir, info)
    check_db(c, envdir, appdir)
    install_db_schema(c, envdir, appdir)
    make_admin_user(c, envdir, appdir, info)

    print()
    print(bold("============================================================"))
    print()
    print(bold("  Okay, you should be ready to go!"))
    print()
    print(bold("============================================================"))
    print()
    print("start your development web app with this command:")
    print()
    print("    cd {}".format(envdir))
    if sys.platform == 'win32':
        print(r"    Scripts\pserve --reload file+ini:app\web.conf")
    else:
        print("    bin/pserve --reload file+ini:app/web.conf")
    print()
    print("then check out your development web app at:")
    print()
    print("    http://localhost:9080")
    print()


def collect_info():
    """
    Collect misc. dev info from user
    """
    info = {}
    print()
    print(bold("Welcome to Theo, the order system."))

    config = configparser.ConfigParser()
    if config.read(os.path.join(here, 'settings.ini')):
        if config.has_section('devbootstrap'):
            info = dict(config.items('devbootstrap'))

    try:
        print()
        print("Please enter the details for your Theo database.")
        print()
        info['dbhost'] = do_prompt('DB host',
                                   default=info.get('dbhost', 'localhost'))
        info['dbname'] = do_prompt('DB name',
                                   default=info.get('dbname', 'theo'))
        info['dbuser'] = do_prompt('DB user',
                                   default=info.get('dbuser', 'rattail'))
        info['dbpass'] = do_prompt('DB password',
                                   default=info.get('dbpass'))

        print()
        print("Please enter the details for your Theo admin user.")
        print()
        info['theouser'] = do_prompt('Theo username',
                                     default=info.get('theouser', 'admin'))
        info['theopass'] = do_prompt('Theo password',
                                     default=info.get('theopass'))

    except (KeyboardInterrupt, EOFError):
        print("\n[Interrupted.]")
        sys.exit(130)  # 128 + SIGINT

    return info


def upgrade_pip(c):
    """
    Upgrade pip and friends
    """
    if sys.platform == 'win32':
        c.run('python -m pip install -U pip')
    else:
        c.run('pip install -U pip')
    c.run('pip install -U setuptools wheel')


def install_app_package(c):
    """
    Install the Theo app package
    """
    project = os.path.abspath(os.path.join(here, os.pardir))
    c.run('pip install -e {}'.format(project))
    c.run('pip install tailbone-theo[app]')


def make_appdir(c, envdir):
    """
    Create the 'app' dir for virtual env
    """
    appdir = os.path.join(envdir, 'app')
    if not os.path.exists(appdir):
        if sys.platform == 'win32':
            c.run('{} make-appdir --path {}'.format(
                os.path.join(envdir, 'Scripts', 'rattail'),
                appdir))
        else:
            c.run('{}/bin/rattail make-appdir --path {}'.format(
                envdir, appdir))
    return appdir


def make_configs(c, envdir, appdir, info):
    """
    Create app config files
    """
    # rattail.conf
    if not os.path.exists(os.path.join(appdir, 'rattail.conf')):
        with open('rattail.conf') as f:
            contents = f.read()
        contents = contents.replace('<ENVDIR>', envdir)
        contents = contents.replace('<SEP>', os.sep)
        contents = contents.replace('<DBHOST>', info['dbhost'])
        contents = contents.replace('<DBNAME>', info['dbname'])
        contents = contents.replace('<DBUSER>', info['dbuser'])
        contents = contents.replace('<DBPASS>', info['dbpass'])
        with open(os.path.join(appdir, 'rattail.conf'), 'w') as f:
            f.write(contents)

    # quiet.conf
    if not os.path.exists(os.path.join(appdir, 'quiet.conf')):
        if sys.platform == 'win32':
            c.run('{} make-config -T quiet -O {}'.format(
                  os.path.join(envdir, 'Scripts', 'rattail'),
                  appdir))
        else:
            c.run('{}/bin/rattail make-config -T quiet -O {}'.format(
                envdir, appdir))

    # nodb.conf
    if not os.path.exists(os.path.join(appdir, 'nodb.conf')):
        shutil.copyfile('nodb.conf', os.path.join(appdir, 'nodb.conf'))

    # web.conf
    if not os.path.exists(os.path.join(appdir, 'web.conf')):
        with open('web.conf') as f:
            contents = f.read()
        contents = contents.replace('<ENVDIR>', envdir)
        contents = contents.replace('<SEP>', os.sep)
        with open(os.path.join(appdir, 'web.conf'), 'w') as f:
            f.write(contents)


def check_db(c, envdir, appdir):
    """
    Do basic sanity checks for Theo database
    """
    if sys.platform == 'win32':
        c.run('{} -c {} -c {} --no-versioning checkdb'.format(
            os.path.join(envdir, 'Scripts', 'rattail'),
            os.path.join(appdir, 'quiet.conf'),
            os.path.join(appdir, 'nodb.conf')))
    else:
        c.run('{0}/bin/rattail -c {1}/quiet.conf -c {1}/nodb.conf --no-versioning checkdb'.format(
            envdir, appdir))


def install_db_schema(c, envdir, appdir):
    """
    Install the schema for Theo database
    """
    if sys.platform == 'win32':
        c.run('{} -c {} upgrade heads'.format(
              os.path.join(envdir, 'Scripts', 'alembic'),
              os.path.join(appdir, 'rattail.conf')))
    else:
        c.run('{}/bin/alembic -c {}/rattail.conf upgrade heads'.format(
            envdir, appdir))


def make_admin_user(c, envdir, appdir, info):
    """
    Make an admin user in the Theo database
    """
    if sys.platform == 'win32':
        c.run('{} -c {} make-user --admin {} --password {}'.format(
              os.path.join(envdir, 'Scripts', 'rattail'),
              os.path.join(appdir, 'quiet.conf'),
              info['theouser'], info['theopass']))
    else:
        c.run('{}/bin/rattail -c {}/quiet.conf make-user --admin {} --password {}'.format(
            envdir, appdir, info['theouser'], info['theopass']))
