from collections import OrderedDict
import os.path

import click
import sys

import functools
import wattle
import yaml

from bricks.commons import get_name
from bricks.help_printer import ProjectHelpPrinter
from bricks.logger import logger
from bricks.schema import Project


@click.group(help='Development workflow made easy')
def cli():
    pass


default_bricks_yml = OrderedDict([
    ('metadata', OrderedDict([
        ('name', get_name()),
        ('version', '0.0.1'),
        ('description', 'Auto-generated by bricks'),
        ('tags', []),
    ])),
    ('plugins', [
        {'name': 'dockercompose_devkit',
         'params': {'image': 'python:3.6'}}
    ]),
    ('commands', [OrderedDict([
        ('name', 'say_hello'),
        ('driver', 'local'),
        ('commands', ['echo "Hello there"'])
    ])])
])


def dict_representer(dumper, data):
    return dumper.represent_dict(data.items())


yaml.Dumper.add_representer(OrderedDict,
                            dict_representer)


@cli.command('init')
def init():
    check_initialized()
    project = load_project()
    for plugin in project.plugins:
        logger.info('Initializing {}'.format(plugin.name))


def check_initialized():
    if not os.path.exists('bricks.yml'):
        logger.error('Project not initialized. Create bricks.yml first')
        sys.exit(-1)


def load_project():
    schema = wattle.load_schema(Project)
    return schema.read('bricks.yml')


def receive_project(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        check_initialized()
        project = load_project()
        return func(project=project, *args, **kwargs)

    return wrapper


@cli.command('help', help='Displays everything that needs to be known')
@receive_project
def help(project):
    ProjectHelpPrinter(project).print_help()


def build_params(param):
    params = {}
    for item in param:
        k, v = item.split('=', maxsplit=1)
        params[k] = v
    return params


@cli.command('run', help='Runs the COMMAND command for this project')
@click.argument('command')
@click.option('-p', '--param', multiple=True,
              help='Set extra env vars for the command that is running')
@receive_project
def run(project, command, param):
    exec_summary = project.run_command(command, build_params(param))
    if not exec_summary.is_successful():
        logger.error('Execution failed (check the output for more info)')
        sys.exit(-1)


@cli.command('init', help='Make sure the project is in the desired state')
@receive_project
def init(project):
    success = project.initialize_plugins()
    if not success:
        sys.exit(-1)
