# -*- coding: utf-8 -*-
from enum import Enum
from plumpy.utils import AttributesDict
from aiida.orm.calculation import Calculation
from aiida.orm.workflow import Workflow

__all__ = ['Awaitable', 'AwaitableTarget', 'AwaitableAction', 'construct_awaitable']


class AwaitableTarget(Enum):
    """
    Enum that describes the class of the target a given awaitable
    """
    CALCULATION = 'calculation'
    WORKFLOW = 'workflow'


class AwaitableAction(Enum):
    """
    Enum that describes the action to be taken for a given awaitable
    """
    ASSIGN = 'assign'
    APPEND = 'append'


class Awaitable(AttributesDict):
    """
    This is some reference
    """
    pass


def construct_awaitable(target):
    """
    Construct an instance of the Awaitable class that will contain the information
    related to the action to be taken with respect to the context once the awaitable
    object is completed.

    The awaitable is a simple dictionary with the following keys

        * pk: the pk of the node that is being waited on
        * action: the context action to be performed upon completion
        * outputs: a boolean that toggles whether the node itself

    Currently the only awaitable classes are Calculation and Workflow
    The only awaitable actions are the Assign and Append operators
    """
    if isinstance(target, Awaitable):
        return target

    awaitable = Awaitable(**{
        'pk': target.pk,
        'action': AwaitableAction.ASSIGN,
        'outputs': False,
    })

    if isinstance(target, Calculation):
        awaitable.target = AwaitableTarget.CALCULATION
    elif isinstance(target, Workflow):
        awaitable.target = AwaitableTarget.WORKFLOW
    else:
        raise ValueError('invalid class for awaitable target: {}'.format(type(target)))

    return awaitable
