# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.


"""
Module for offchain operations. Connection to resdb nodes not required!
"""

import logging
from functools import singledispatch

from .transaction import Input, Transaction, TransactionLink, _fulfillment_from_details
from .exceptions import KeypairMismatchException

from .exceptions import ResdbException, MissingPrivateKeyError
from .utils import (
    CreateOperation,
    TransferOperation,
    _normalize_operation,
)

logger = logging.getLogger(__name__)


@singledispatch
def _prepare_transaction(
    operation, signers=None, recipients=None, asset=None, metadata=None, inputs=None
):
    raise ResdbException(
        (
            "Unsupported operation: {}. "
            'Only "CREATE" and "TRANSFER" are supported.'.format(operation)
        )
    )


@_prepare_transaction.register(CreateOperation)
def _prepare_create_transaction_dispatcher(operation, **kwargs):
    del kwargs["inputs"]
    return prepare_create_transaction(**kwargs)


@_prepare_transaction.register(TransferOperation)
def _prepare_transfer_transaction_dispatcher(operation, **kwargs):
    del kwargs["signers"]
    return prepare_transfer_transaction(**kwargs)


def prepare_transaction(
    *,
    operation="CREATE",
    signers=None,
    recipients=None,
    asset=None,
    metadata=None,
    inputs=None
) -> dict:
    """! Prepares a transaction payload, ready to be fulfilled. Depending on
    the value of ``operation``, simply dispatches to either
    :func:`~.prepare_create_transaction` or
    :func:`~.prepare_transfer_transaction`.

    @param operation (str): The operation to perform. Must be ``'CREATE'``
            or ``'TRANSFER'``. Case insensitive. Defaults to ``'CREATE'``.
    @param signers (:obj:`list` | :obj:`tuple` | :obj:`str`, optional):
            One or more public keys representing the issuer(s) of
            the asset being created. Only applies for ``'CREATE'``
            operations. Defaults to ``None``.
    @param recipients (:obj:`list` | :obj:`tuple` | :obj:`str`, optional):
            One or more public keys representing the new recipients(s)
            of the asset being created or transferred.
            Defaults to ``None``.
    @param asset (:obj:`dict`, optional):
            The asset to be created orctransferred.
            MUST be supplied for ``'TRANSFER'`` operations.
            Defaults to ``None``.
    @param metadata (:obj:`dict`, optional):
            Metadata associated with the
            transaction. Defaults to ``None``.
    @param inputs (:obj:`dict` | :obj:`list` | :obj:`tuple`, optional):
            One or more inputs holding the condition(s) that this
            transaction intends to fulfill. Each input is expected to
            be a :obj:`dict`. Only applies to, and MUST be supplied for,
            ``'TRANSFER'`` operations.

    @return The prepared transaction

    @exception :class:`~.exceptions.ResdbException`: If ``operation`` is
        not ``'CREATE'`` or ``'TRANSFER'``.

    .. important::

        **CREATE operations**

        * ``signers`` MUST be set.
        * ``recipients``, ``asset``, and ``metadata`` MAY be set.
        * If ``asset`` is set, it MUST be in the form of::

            {
                'data': {
                    ...
                }
            }

        * The argument ``inputs`` is ignored.
        * If ``recipients`` is not given, or evaluates to
          ``False``, it will be set equal to ``signers``::

            if not recipients:
                recipients = signers

        **TRANSFER operations**

        * ``recipients``, ``asset``, and ``inputs`` MUST be set.
        * ``asset`` MUST be in the form of::

            {
                'id': '<Asset ID (i.e. TX ID of its CREATE transaction)>'
            }

        * ``metadata`` MAY be set.
        * The argument ``signers`` is ignored.

    """
    operation = _normalize_operation(operation)
    return _prepare_transaction(
        operation,
        signers=signers,
        recipients=recipients,
        asset=asset,
        metadata=metadata,
        inputs=inputs,
    )


def prepare_create_transaction(*, signers, recipients=None, asset=None, metadata=None):
    """! Prepares a ``"CREATE"`` transaction payload, ready to be
    fulfilled.

    @param signers (:obj:`list` | :obj:`tuple` | :obj:`str`):
            One or more public keys representing
            the issuer(s) of the asset being created.
    @param recipients (:obj:`list` | :obj:`tuple` | :obj:`str`, optional):
            One or more public keys representing
            the new recipients(s) of the asset being created. Defaults to ``None``.
    @param asset (:obj:`dict`, optional): The asset to be created. Defaults to ``None``.
    @param metadata (:obj:`dict`, optional): Metadata associated with the transaction. Defaults to ``None``.

    @return The prepared ``"CREATE"`` transaction.

    .. important::

        * If ``asset`` is set, it MUST be in the form of::

                {
                    'data': {
                        ...
                    }
                }

        * If ``recipients`` is not given, or evaluates to
          ``False``, it will be set equal to ``signers``::

            if not recipients:
                recipients = signers

    """
    if not isinstance(signers, (list, tuple)):
        signers = [signers]
    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    elif isinstance(signers, tuple):
        signers = list(signers)

    if not recipients:
        recipients = [(signers, 1)]
    elif not isinstance(recipients, (list, tuple)):
        recipients = [([recipients], 1)]
    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    elif isinstance(recipients, tuple):
        recipients = [(list(recipients), 1)]

    transaction = Transaction.create(
        signers,
        recipients,
        metadata=metadata,
        asset=asset["data"] if asset else None,
    )
    return transaction.to_dict()


def prepare_transfer_transaction(*, inputs, recipients, asset, metadata=None):
    """! Prepares a ``"TRANSFER"`` transaction payload, ready to be
    fulfilled.

    @param inputs (:obj:`dict` | :obj:`list` | :obj:`tuple`):
                One or more inputs holding the condition(s) that this transaction
                intends to fulfill. Each input is expected to be a
                :obj:`dict`.
    @param recipients (:obj:`str` | :obj:`list` | :obj:`tuple`):
            One or more public keys representing the
            new recipients(s) of the
            asset being transferred.
    @param asset (:obj:`dict`): A single-key dictionary holding the ``id``
            of the asset being transferred with this transaction.
    @param metadata (:obj:`dict`): Metadata associated with the
            transaction. Defaults to ``None``.

    @return The prepared ``"TRANSFER"`` transaction.

    .. important::

        * ``asset`` MUST be in the form of::

            {
                'id': '<Asset ID (i.e. TX ID of its CREATE transaction)>'
            }

    Example:

        # .. todo:: Replace this section with docs.

        In case it may not be clear what an input should look like, say
        Alice (public key: ``'3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf'``)
        wishes to transfer an asset over to Bob
        (public key: ``'EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA'``).
        Let the asset creation transaction payload be denoted by
        ``tx``::

            # noqa E501
            >>> tx
                {'asset': {'data': {'msg': 'Hello Resdb!'}},
                 'id': '9650055df2539223586d33d273cb8fd05bd6d485b1fef1caf7c8901a49464c87',
                 'inputs': [{'fulfillment': {'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
                                             'type': 'ed25519-sha-256'},
                             'fulfills': None,
                             'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
                 'metadata': None,
                 'operation': 'CREATE',
                 'outputs': [{'amount': '1',
                              'condition': {'details': {'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
                                                        'type': 'ed25519-sha-256'},
                                            'uri': 'ni:///sha-256;7ApQLsLLQgj5WOUipJg1txojmge68pctwFxvc3iOl54?fpt=ed25519-sha-256&cost=131072'},
                              'public_keys': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
                 'version': '2.0'}

        Then, the input may be constructed in this way::

            output_index
            output = tx['transaction']['outputs'][output_index]
            input_ = {
                'fulfillment': output['condition']['details'],
                'input': {
                    'output_index': output_index,
                    'transaction_id': tx['id'],
                },
                'owners_before': output['public_keys'],
            }

        Displaying the input on the prompt would look like::

            >>> input_
            {'fulfillment': {
              'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
              'type': 'ed25519-sha-256'},
             'input': {'output_index': 0,
              'transaction_id': '9650055df2539223586d33d273cb8fd05bd6d485b1fef1caf7c8901a49464c87'},
             'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}


        To prepare the transfer:

        >>> prepare_transfer_transaction(
        ...     inputs=input_,
        ...     recipients='EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA',
        ...     asset=tx['transaction']['asset'],
        ... )

    """
    if not isinstance(inputs, (list, tuple)):
        inputs = (inputs,)
    if not isinstance(recipients, (list, tuple)):
        recipients = [([recipients], 1)]

    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    if isinstance(recipients, tuple):
        recipients = [(list(recipients), 1)]

    fulfillments = [
        Input(
            _fulfillment_from_details(input_["fulfillment"]),
            input_["owners_before"],
            fulfills=TransactionLink(
                txid=input_["fulfills"]["transaction_id"],
                output=input_["fulfills"]["output_index"],
            ),
        )
        for input_ in inputs
    ]

    transaction = Transaction.transfer(
        fulfillments,
        recipients,
        asset_id=asset["id"],
        metadata=metadata,
    )
    return transaction.to_dict()


def fulfill_transaction(transaction, *, private_keys) -> dict:
    """! Fulfills the given transaction.

    @param transaction The transaction to be fulfilled.
    @param private_keys One or more private keys to be
            used for fulfilling the transaction.

    @return The fulfilled transaction payload, ready to be sent to a
            ResDB federation.

    @exception :exc:`~.exceptions.MissingPrivateKeyError`: If a private
        key is missing.
    """
    if not isinstance(private_keys, (list, tuple)):
        private_keys = [private_keys]

    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    if isinstance(private_keys, tuple):
        private_keys = list(private_keys)

    transaction_obj = Transaction.from_dict(transaction)
    try:
        signed_transaction = transaction_obj.sign(private_keys)
    except KeypairMismatchException as exc:
        raise MissingPrivateKeyError("A private key is missing!") from exc

    return signed_transaction.to_dict()
