"""Registry API methods"""
import logging
import click
import docker

logger=logging.getLogger('mldock')

def compute_progress(current, max_value=10):
    """
        compute the progress bar update

        args:
            current (int): current count of progress bar
            max_value (int): (default=10) maximum length of progress bar
        returns:
            (int): updated progress bar
    """
    if current > max_value:
        multiple = current // max_value
        current = current - max_value * multiple

    return current

def get_layer_state(
    stream: str,
    layer_id: str,
    state: dict = None,
    **kwargs
):
    """
        Computes a status update to the state of layer during a push.
        Additionally, adds a progress bar and flexible fill character.

        args:
            stream (str): stream message
            layer_id (str): stream layer id
            state (dict) (default=None) current state
        kwargs:
            progress (str): (default = '') starting progress bar string
            fill_char (str): (default='=') fill char to use as progress bar
            increment (str): (default=2) progress bar char increment to use
            max_value (str): (default=40) maximum progress bar length
            status_tag (str): (default='pushing') key to use to look for updates
    """
    progress = kwargs.get('progress', '')
    fill_char = kwargs.get('fill_char', '=')
    increment = kwargs.get('increment', 2)
    max_value = kwargs.get('max_value', 40)
    status_tag = kwargs.get('status_tag', 'pushing')

    try:

        if status_tag.lower() == 'pushing':
            # progress = ''
            if stream.lower() == status_tag.lower():
                current_layer = state[layer_id]
                current_progress = (
                    current_layer['progress']
                        .replace("[",'')
                        .replace("]",'')
                        .replace(">",'')
                )
                current_progress = len(current_progress)
                progress = compute_progress(current_progress, max_value=max_value) + increment
                progress = fill_char * progress
                progress = "[{}>]".format(progress)

        state.update(
            {layer_id: {'message': stream, 'progress': progress}}
        )
    except KeyError:
        pass

    return state

def stateful_log_emitter(line: dict, status_tag: str, states: dict = None):
    """
        stateful log emitter

        args:
            line (dict): current record of logs
            status_tag (str): key to use to update state
            states (dict): current state of logs
    """
    if states is None:
        states = {}

    error = line.get('error', None)
    error_detail = line.get('errorDetail', None)
    if error is not None:
        logger.error('{}\n{}'.format(error, error_detail))

    stream = line.get('status','')
    layer_id = line.get('id','')
    progress = line.get('progress','')

    # perform status update, using layer_id as key
    states = get_layer_state(stream, layer_id, states, progress=progress, status_tag=status_tag)

    # clear terminal to allow for friendlier update
    click.clear()

    # emit current state to stdout
    for key, value in states.items():
        logger.info(
            "{KEY}: {MESSAGE} {PROGRESS}".format(
                KEY=key,
                MESSAGE=value['message'],
                PROGRESS=value['progress']
            )
        )

    return states

def push_image_to_repository(
    image_repository: str,
    auth_config: dict,
    tag='latest'
):
    """
        Push image to repository in registry. Using auth_config this will Authenticate client.
    """
    client = docker.from_env()

    push_response = client.images.push(
        repository=image_repository,
        tag=tag,
        stream=True,
        decode=True,
        auth_config=auth_config
    )

    states = {}
    for line in push_response:
        states = stateful_log_emitter(line=line, states=states, status_tag='Pushing')
    return states

def pull_image_from_repository(
    image_repository: str,
    auth_config: dict,
    tag='latest'
):
    """
        Pull image from repository in registry. Using auth_config this will Authenticate client.
    """
    client = docker.from_env()

    pull_response = client.api.pull(
        repository=image_repository,
        tag=tag,
        stream=True,
        decode=True,
        auth_config=auth_config
    )

    states = {}
    for line in pull_response:
        states = stateful_log_emitter(line=line, states=states, status_tag='Downloading')
    return states
