# -*- coding: utf-8 -*-
from __future__ import with_statement, absolute_import, unicode_literals

import glob
import os.path as op
import re

import click

from ..context import pass_context, on_finished, on_started


def get_image_id(events):
    image_id = None
    for event in events:
        if 'stream' in event:
            match = re.search(r'Successfully built ([0-9a-f]+)',
                              event.get('stream', ''))
            if match:
                image_id = match.group(1)
    if image_id is None:
        raise click.ClickException("Cannot get image id")
    return image_id


def try_attached_image(ctx, name):
    available_images = [', '.join(im["RepoTags"]) for im in
                        ctx.docker.get_images(all_images=False)]
    all_images = list(set([', '.join(im["RepoTags"]) for im in
                           ctx.docker.get_images(all_images=True)]))
    if name in all_images:
        blue_image_name = click.style(name, fg="blue")
        if name not in available_images:
            click.echo("Attached '%s' image to the workdir"
                       % blue_image_name)
        else:
            click.echo("Image '%s' is already in the workdir"
                       % blue_image_name)
        ctx.docker.add_image(name)
        return True
    return False


@click.command('build')
@click.option('--force-rm', is_flag=True, default=False,
              help="Always remove intermediate containers, even after "
                   "unsuccessful builds")
@click.option('--no-cache', is_flag=True, default=False,
              help="Do not use cache when building the image")
@click.option('--pull', is_flag=True, default=False,
              help="Attempt to pull a newer version of the image")
@click.option('-q', '--quiet', is_flag=True, default=False,
              help="Suppress the verbose output generated by the containers")
@click.option('--rm/--no-rm', is_flag=True, default=True,
              help="Remove intermediate containers after a successful build")
@click.option('--rebuild/--no-rebuild', is_flag=True, default=True,
              help="Rebuild images even if already done")
@pass_context
@on_finished(lambda ctx: ctx.state.dump())
@on_finished("clean")
@on_started("stop")
@on_started(lambda ctx: ctx.assert_valid_env())
def cli(ctx, force_rm, no_cache, pull, quiet, rm, rebuild):
    """Build base images"""
    ctx.log('Starting oardocker build')
    dockerfiles = glob.glob(op.join(ctx.envdir, "images", "*", "Dockerfile"))

    def build_order(x):
        if ctx.state.manifest.get('build_order', []):
            for i, image_name in enumerate(ctx.state.manifest['build_order']):
                dirpath = op.join(ctx.envdir, "images", image_name)
                if dirpath in x:
                    return i
        else:
            if x[0].isdigit():
                return int(x.partition(' ')[0]), x
        return float('inf')

    dockerfiles = sorted(dockerfiles, key=build_order)

    def get_prefix_width():
        for dockerfile in dockerfiles:
            yield len(op.basename(op.dirname(dockerfile)))
    max_prefix_width = max(get_prefix_width())
    for dockerfile in dockerfiles:
        dirname = op.dirname(dockerfile)
        name = op.basename(dirname)
        if name in ctx.state.manifest.get('install_on', []):
            tag = "%s:base" % ctx.image_name(name)
        else:
            tag = "%s:latest" % ctx.image_name(name)
        padding = ' ' * (max_prefix_width - len(name))
        prefix = click.style(''.join([padding, name, ' | ']), fg="green")
        args = ["build"]
        if force_rm:
            args.append("--force-rm")
        if no_cache:
            args.append("--no-cache")
        if pull:
            args.append("--pull")
        if quiet:
            args.append("--quiet")
        if rm:
            args.append("--rm")
        args.extend(["--tag", tag])
        args.append(dirname)
        if rebuild or not try_attached_image(ctx, tag):
            for line in ctx.docker.cli(args, _iter=True):
                ctx.log(prefix + line, nl=False)
            ctx.state["images"].append(tag)
