#!/usr/bin/env python3
import os

import click
from fabric.colors import red, green, yellow
from fabric.api import hide, abort

from classes.config import Config
from classes.local_git_wrapper import LocalGitWrapper
from classes.deployment_server_actions import DeploymentServerActions

VERBOSE_LEVEL = 3


def log(message, color):
    """
    Log with the verbose level

    :param message: string message
    :param color:
    :return:
    """
    if color == yellow and VERBOSE_LEVEL >= 2 or color == green and VERBOSE_LEVEL > 0 or color == red:
        print(color(message))


def deployment(config_path, deployment_type):
    try:
        log('Read config item', yellow)
        config_item = Config(config_path).config_item(deployment_type)
        server_actions = DeploymentServerActions(config_item)
        log('Read hash of specified branch', yellow)
        to_deploy_branch_hash = LocalGitWrapper.get_branch_hash(config_item.branch)
        log('Specified branch was: {}'.format(to_deploy_branch_hash), yellow)
        log('Read last deployed branch hash on server...', yellow)
        current_server_branch_hash = server_actions.get_current_revision()
        log('Last deployed branch on server was: {}'.format(current_server_branch_hash), yellow)

        if not current_server_branch_hash:
            log('There is no deployment on the server.\n'
                'You want to deploy the following commit hash: {}'.format(to_deploy_branch_hash), red)
        else:
            log(LocalGitWrapper.get_differ_git_commit_messages(current_server_branch_hash, to_deploy_branch_hash), red)

        answer = click.prompt('Do you want to deploy?', type=str, default='y')
        if answer != 'y':
            abort('Thank you! See you later :*')

        if not server_actions.has_virtualenv():
            log('Creating virtualenv...', yellow)
            server_actions.create_virtualenv()

        source_path_of_artifact = '/tmp/{}.gz'.format(to_deploy_branch_hash)
        log('Zip artifact of branch \"{branch_name}\"'.format(branch_name=config_item.branch, ), yellow)
        LocalGitWrapper.create_git_archive_of_branch(to_deploy_branch_hash, source_path_of_artifact)
        log('Upload artifact to server...', yellow)
        server_actions.push_file_to_server(source_path_of_artifact, source_path_of_artifact)
        log('Remove artifact...', yellow)
        LocalGitWrapper.remove_git_archive_of_branch(source_path_of_artifact)

        server_deploy_to_path = os.path.join(config_item.deploy_dir, to_deploy_branch_hash)

        log('Create directory to unpack the artifact: {}'.format(server_deploy_to_path), yellow)
        server_actions.create_directory(server_deploy_to_path)
        log('Unpack the artifact to source path: {}'.format(server_deploy_to_path), yellow)
        server_actions.unpack_tar_to_source(source_path_of_artifact, server_deploy_to_path)
        log('Remove artifact from server...', yellow)
        server_actions.remove_file_or_dir(source_path_of_artifact)

        log('Stopping services', yellow)
        server_actions.stop_services()

        log('Updating virtualenv', yellow)
        server_actions.update_virtualenv()

        log('Executing all manage.py commands', yellow)
        server_actions.execute_all_manage_py_commands(to_deploy_branch_hash)

        log('Set deployed link to new deployment', yellow)
        server_actions.set_symbolic_link(
            server_deploy_to_path,
            server_actions.deployed_path,
        )

        log('Set virtualenv link to new deployment', yellow)
        server_actions.set_symbolic_link(
            server_actions.virtualenv_path,
            os.path.join(server_deploy_to_path, 'virtualenv'),
        )

        log('Starting services', yellow)
        server_actions.start_services()

    except Exception as deployment_exception:
        log(unicode(deployment_exception), red)
        answer = click.prompt('Ooops! There was an error, do you want to rollback? (y, n)', type=str, default='n')
        if answer == 'y':
            # rollback
            pass


@click.command()
@click.option('--config-path', help='The path of the config file')
@click.option(
    '--verbose',
    type=click.INT,
    default=VERBOSE_LEVEL,
    help='Verbose mode (0 = only errors, 1 = normal outputs, 2 = debugging level, 3 = high debugging level)'
)
@click.argument('deployment_type')
def main(config_path, verbose, deployment_type):
    """
    ** DJANGO-DEPLOY **
    django-deploy helps you to deploy your django application to a custom server via ssh
    TBD

    """
    global VERBOSE_LEVEL
    VERBOSE_LEVEL = verbose
    if VERBOSE_LEVEL != 3:
        with hide('output', 'running', 'warnings'):
            deployment(config_path, deployment_type)
    else:
        deployment(config_path, deployment_type)


if __name__ == '__main__':
    # Hide everything that comes from fabrics if verbose level != 2
    main()
