# 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.


"""!
Transaction related models to parse and construct transaction
payloads.

Attributes:
    UnspentOutput (namedtuple): Object holding the information
        representing an unspent output.

"""
from collections import namedtuple
from copy import deepcopy
from functools import reduce

import base58
from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256
from cryptoconditions.exceptions import (
    ParsingError,
    ASN1DecodeError,
    ASN1EncodeError,
    UnsupportedTypeError,
)
from sha3 import sha3_256

from .crypto import PrivateKey, hash_data
from .exceptions import (
    KeypairMismatchException,
    InvalidHash,
    InvalidSignature,
    AmountError,
    AssetIdMismatch,
    ThresholdTooDeep,
    DoubleSpend,
    InputDoesNotExist,
)
from .utils import serialize


UnspentOutput = namedtuple(
    "UnspentOutput",
    (
        # TODO 'utxo_hash': sha3_256(f'{txid}{output_index}'.encode())
        # 'utxo_hash',   # noqa
        "transaction_id",
        "output_index",
        "amount",
        "asset_id",
        "condition_uri",
    ),
)


class Input(object):
    """! A Input is used to spend assets locked by an Output.
    Wraps around a Crypto-condition Fulfillment.

    fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment
        to be signed with a private key.
    owners_before (:obj:`list` of :obj:`str`): A list of owners after a
        Transaction was confirmed.
    fulfills (:class:`~resdb.transaction. TransactionLink`,
        optional): A link representing the input of a `TRANSFER`
        Transaction.
    """

    def __init__(self, fulfillment, owners_before, fulfills=None):
        """! Create an instance of an :class:`~.Input`.
        @param fulfillment (:class:`cryptoconditions.Fulfillment`): A
            Fulfillment to be signed with a private key.
        @param owners_before (:obj:`list` of :obj:`str`): A list of owners
            after a Transaction was confirmed.
        @param fulfills (:class:`~resdb.transaction.
                TransactionLink`, optional): A link representing the input
            of a `TRANSFER` Transaction.
        """
        if fulfills is not None and not isinstance(fulfills, TransactionLink):
            raise TypeError("`fulfills` must be a TransactionLink instance")
        if not isinstance(owners_before, list):
            raise TypeError("`owners_after` must be a list instance")

        self.fulfillment = fulfillment
        self.fulfills = fulfills
        self.owners_before = owners_before

    def __eq__(self, other):
        # TODO: If `other !== Fulfillment` return `False`
        return self.to_dict() == other.to_dict()

    def to_dict(self):
        """! Transforms the object to a Python dictionary.
        If an Input hasn't been signed yet, this method returns a
        dictionary representation.

        @return dict: The Input as an alternative serialization format.
        """
        try:
            fulfillment = self.fulfillment.serialize_uri()
        except (TypeError, AttributeError, ASN1EncodeError, ASN1DecodeError):
            fulfillment = _fulfillment_to_details(self.fulfillment)

        try:
            # NOTE: `self.fulfills` can be `None` and that's fine
            fulfills = self.fulfills.to_dict()
        except AttributeError:
            fulfills = None

        input_ = {
            "owners_before": self.owners_before,
            "fulfills": fulfills,
            "fulfillment": fulfillment,
        }
        return input_

    @classmethod
    def generate(cls, public_keys):
        # TODO: write docstring
        # The amount here does not really matter. It is only use on the
        # output data model but here we only care about the fulfillment
        output = Output.generate(public_keys, 1)
        return cls(output.fulfillment, public_keys)

    @classmethod
    def from_dict(cls, data):
        """! Transforms a Python dictionary to an Input object.
        Note:
            Optionally, this method can also serialize a Cryptoconditions-
            Fulfillment that is not yet signed.

        @param data (dict): The Input to be transformed.
        @return :class:`~resdb.transaction.Input`
        @exception InvalidSignature: If an Input's URI couldn't be parsed.
        """
        fulfillment = data["fulfillment"]
        if not isinstance(fulfillment, (Fulfillment, type(None))):
            try:
                fulfillment = Fulfillment.from_uri(data["fulfillment"])
            except ASN1DecodeError:
                # TODO Remove as it is legacy code, and simply fall back on
                # ASN1DecodeError
                raise InvalidSignature("Fulfillment URI couldn't been parsed")
            except TypeError:
                # NOTE: See comment about this special case in
                #       `Input.to_dict`
                fulfillment = _fulfillment_from_details(data["fulfillment"])
        fulfills = TransactionLink.from_dict(data["fulfills"])
        return cls(fulfillment, data["owners_before"], fulfills)


def _fulfillment_to_details(fulfillment):
    """! Encode a fulfillment as a details dictionary
    Args:
        @param fulfillment (:class:`cryptoconditions.Fulfillment`): Crypto-conditions Fulfillment object
    """

    if fulfillment.type_name == "ed25519-sha-256":
        return {
            "type": "ed25519-sha-256",
            "public_key": base58.b58encode(fulfillment.public_key).decode(),
        }

    if fulfillment.type_name == "threshold-sha-256":
        subconditions = [
            _fulfillment_to_details(cond["body"]) for cond in fulfillment.subconditions
        ]
        return {
            "type": "threshold-sha-256",
            "threshold": fulfillment.threshold,
            "subconditions": subconditions,
        }

    raise UnsupportedTypeError(fulfillment.type_name)


def _fulfillment_from_details(data, _depth=0):
    """! Load a fulfillment for a signing spec dictionary
    @param data tx.output[].condition.details dictionary
    """
    if _depth == 100:
        raise ThresholdTooDeep()

    if data["type"] == "ed25519-sha-256":
        public_key = base58.b58decode(data["public_key"])
        return Ed25519Sha256(public_key=public_key)

    if data["type"] == "threshold-sha-256":
        threshold = ThresholdSha256(data["threshold"])
        for cond in data["subconditions"]:
            cond = _fulfillment_from_details(cond, _depth + 1)
            threshold.add_subfulfillment(cond)
        return threshold

    raise UnsupportedTypeError(data.get("type"))


class TransactionLink(object):
    """! An object for unidirectional linking to a Transaction's Output.
    Attributes:
        txid (str, optional): A Transaction to link to.
        output (int, optional): An output's index in a Transaction with id
        `txid`.
    """

    def __init__(self, txid=None, output=None):
        """! Create an instance of a :class:`~.TransactionLink`.
        Note:
            In an IPLD implementation, this class is not necessary anymore,
            as an IPLD link can simply point to an object, as well as an
            objects properties. So instead of having a (de)serializable
            class, we can have a simple IPLD link of the form:
            `/<tx_id>/transaction/outputs/<output>/`.

            @param txid (str): A Transaction to link to.
            @param output An (int): Outputs's index in a Transaction
            with id `txid`.
        """
        self.txid = txid
        self.output = output

    def __bool__(self):
        return self.txid is not None and self.output is not None

    def __eq__(self, other):
        # TODO: If `other !== TransactionLink` return `False`
        return self.to_dict() == other.to_dict()

    def __hash__(self):
        return hash((self.txid, self.output))

    @classmethod
    def from_dict(cls, link):
        """! Transforms a Python dictionary to a TransactionLink object.

        @param link (dict): The link to be transformed.

        @return :class:`~resdb.transaction.TransactionLink`
        """
        try:
            return cls(link["transaction_id"], link["output_index"])
        except TypeError:
            return cls()

    def to_dict(self):
        """! Transforms the object to a Python dictionary.
        @return The link as an alternative serialization format.
        """
        if self.txid is None and self.output is None:
            return None
        else:
            return {
                "transaction_id": self.txid,
                "output_index": self.output,
            }

    def to_uri(self, path=""):
        if self.txid is None and self.output is None:
            return None
        return "{}/transactions/{}/outputs/{}".format(path, self.txid, self.output)


class Output(object):
    """! An Output is used to lock an asset.
    Wraps around a Crypto-condition Condition.
        Attributes:
            fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment
                to extract a Condition from.
            public_keys (:obj:`list` of :obj:`str`, optional): A list of
                owners before a Transaction was confirmed.
    """

    MAX_AMOUNT = 9 * 10**18

    def __init__(self, fulfillment, public_keys=None, amount=1):
        """! Create an instance of a :class:`~.Output`.
        Args:
            @param fulfillment (:class:`cryptoconditions.Fulfillment`): A
                Fulfillment to extract a Condition from.
            @param public_keys (:obj:`list` of :obj:`str`, optional): A list of
                owners before a Transaction was confirmed.
            @param amount (int): The amount of Assets to be locked with this
                Output.

            @exception TypeError: if `public_keys` is not instance of `list`.
        """
        if not isinstance(public_keys, list) and public_keys is not None:
            raise TypeError("`public_keys` must be a list instance or None")
        if not isinstance(amount, int):
            raise TypeError("`amount` must be an int")
        if amount < 1:
            raise AmountError("`amount` must be greater than 0")
        if amount > self.MAX_AMOUNT:
            raise AmountError("`amount` must be <= %s" % self.MAX_AMOUNT)

        self.fulfillment = fulfillment
        self.amount = amount
        self.public_keys = public_keys

    def __eq__(self, other):
        # TODO: If `other !== Condition` return `False`
        return self.to_dict() == other.to_dict()

    def to_dict(self):
        """! Transforms the object to a Python dictionary.
        Note:
            A dictionary serialization of the Input the Output was
            derived from is always provided.

            @return The Output as an alternative serialization format.
        """
        # TODO FOR CC: It must be able to recognize a hashlock condition
        #              and fulfillment!
        condition = {}
        try:
            condition["details"] = _fulfillment_to_details(self.fulfillment)
        except AttributeError:
            pass

        try:
            condition["uri"] = self.fulfillment.condition_uri
        except AttributeError:
            condition["uri"] = self.fulfillment

        output = {
            "public_keys": self.public_keys,
            "condition": condition,
            "amount": str(self.amount),
        }
        return output

    @classmethod
    def generate(cls, public_keys, amount):
        """! Generates a Output from a specifically formed tuple or list.
        Note:
            If a ThresholdCondition has to be generated where the threshold
            is always the number of subconditions it is split between, a
            list of the following structure is sufficient:
            [(address|condition)*, [(address|condition)*, ...], ...]

        @param public_keys (:obj:`list` of :obj:`str`): The public key of
            the users that should be able to fulfill the Condition
            that is being created.
        @param amount (:obj:`int`): The amount locked by the Output.
        @return An Output that can be used in a Transaction.

        @exception TypeError: If `public_keys` is not an instance of `list`.
        @exception ValueError: If `public_keys` is an empty list.
        """
        threshold = len(public_keys)
        if not isinstance(amount, int):
            raise TypeError("`amount` must be a int")
        if amount < 1:
            raise AmountError("`amount` needs to be greater than zero")
        if not isinstance(public_keys, list):
            raise TypeError("`public_keys` must be an instance of list")
        if len(public_keys) == 0:
            raise ValueError("`public_keys` needs to contain at least one" "owner")
        elif len(public_keys) == 1 and not isinstance(public_keys[0], list):
            if isinstance(public_keys[0], Fulfillment):
                ffill = public_keys[0]
            else:
                ffill = Ed25519Sha256(public_key=base58.b58decode(public_keys[0]))
            return cls(ffill, public_keys, amount=amount)
        else:
            # Threshold conditions not supported by resdb yet
            initial_cond = ThresholdSha256(threshold=threshold)
            threshold_cond = reduce(cls._gen_condition, public_keys, initial_cond)
            return cls(threshold_cond, public_keys, amount=amount)

    @classmethod
    def _gen_condition(cls, initial, new_public_keys):
        """! Generates ThresholdSha256 conditions from a list of new owners.
        Note:
            This method is intended only to be used with a reduce function.
            For a description on how to use this method, see
            :meth:`~.Output.generate`.
        Args:
            @param initial (:class:`cryptoconditions.ThresholdSha256`): A Condition representing the overall root.
            @param new_public_keys (:obj:`list` of :obj:`str`|str): A list of new
                owners or a single new owner.
            @return :class:`cryptoconditions.ThresholdSha256`:
        """
        try:
            threshold = len(new_public_keys)
        except TypeError:
            threshold = None

        if isinstance(new_public_keys, list) and len(new_public_keys) > 1:
            ffill = ThresholdSha256(threshold=threshold)
            reduce(cls._gen_condition, new_public_keys, ffill)
        elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1:
            raise ValueError("Sublist cannot contain single owner")
        else:
            try:
                new_public_keys = new_public_keys.pop()
            except AttributeError:
                pass
            # NOTE: Instead of submitting base58 encoded addresses, a user
            #       of this class can also submit fully instantiated
            #       Cryptoconditions. In the case of casting
            #       `new_public_keys` to a Ed25519Fulfillment with the
            #       result of a `TypeError`, we're assuming that
            #       `new_public_keys` is a Cryptocondition then.
            if isinstance(new_public_keys, Fulfillment):
                ffill = new_public_keys
            else:
                ffill = Ed25519Sha256(public_key=base58.b58decode(new_public_keys))
        initial.add_subfulfillment(ffill)
        return initial

    @classmethod
    def from_dict(cls, data):
        """! Transforms a Python dictionary to an Output object.
        Note:
            To pass a serialization cycle multiple times, a
            Cryptoconditions Fulfillment needs to be present in the
            passed-in dictionary, as Condition URIs are not serializable
            anymore.

        @param data (dict): The dict to be transformed.
        @return :class:`~resdb.transaction.Output`
        """
        try:
            fulfillment = _fulfillment_from_details(data["condition"]["details"])
        except KeyError:
            # NOTE: Hashlock condition case
            fulfillment = data["condition"]["uri"]
        try:
            amount = int(data["amount"])
        except ValueError:
            raise AmountError("Invalid amount: %s" % data["amount"])
        return cls(fulfillment, data["public_keys"], amount)


class Transaction(object):
    """! A Transaction is used to create and transfer assets.
    Note:
        For adding Inputs and Outputs, this class provides methods
        to do so.
    Attributes:
        operation (str): Defines the operation of the Transaction.
        inputs (:obj:`list` of :class:`~resdb.
            transaction.Input`, optional): Define the assets to
            spend.
        outputs (:obj:`list` of :class:`~resdb.
            transaction.Output`, optional): Define the assets to lock.
        asset (dict): Asset payload for this Transaction. ``CREATE``
            Transactions require a dict with a ``data``
            property while ``TRANSFER`` Transactions require a dict with a
            ``id`` property.
        metadata (dict):
            Metadata to be stored along with the Transaction.
        version (string): Defines the version number of a Transaction.
    """

    CREATE = "CREATE"
    TRANSFER = "TRANSFER"
    ALLOWED_OPERATIONS = (CREATE, TRANSFER)
    VERSION = "2.0"

    def __init__(
        self,
        operation,
        asset,
        inputs=None,
        outputs=None,
        metadata=None,
        version=None,
        hash_id=None,
    ):
        """! The constructor allows to create a customizable Transaction.
        Note:
            When no `version` is provided, one is being
            generated by this method.

        @param operation (str): Defines the operation of the Transaction.
        @param asset (dict): Asset payload for this Transaction.
        @param inputs (:obj:`list` of :class:`~resdb.transaction.Input`, optional):Define the assets to
        @param outputs (:obj:`list` of :class:`~resdb.transaction.Output`, optional):Define the assets to lock.
        @param metadata (dict): Metadata to be stored along with the Transaction.
        @param version (string): Defines the version number of a Transaction.
        @param hash_id (string): Hash id of the transaction.
        """
        if operation not in Transaction.ALLOWED_OPERATIONS:
            allowed_ops = ", ".join(self.__class__.ALLOWED_OPERATIONS)
            raise ValueError("`operation` must be one of {}".format(allowed_ops))

        # Asset payloads for 'CREATE' operations must be None or
        # dicts holding a `data` property. Asset payloads for 'TRANSFER'
        # operations must be dicts holding an `id` property.
        if (
            operation == Transaction.CREATE
            and asset is not None
            and not (isinstance(asset, dict) and "data" in asset)
        ):
            raise TypeError(
                (
                    "`asset` must be None or a dict holding a `data` "
                    " property instance for '{}' "
                    "Transactions".format(operation)
                )
            )
        elif operation == Transaction.TRANSFER and not (
            isinstance(asset, dict) and "id" in asset
        ):
            raise TypeError(
                (
                    "`asset` must be a dict holding an `id` property "
                    "for 'TRANSFER' Transactions".format(operation)
                )
            )

        if outputs and not isinstance(outputs, list):
            raise TypeError("`outputs` must be a list instance or None")

        if inputs and not isinstance(inputs, list):
            raise TypeError("`inputs` must be a list instance or None")

        if metadata is not None and not isinstance(metadata, dict):
            raise TypeError("`metadata` must be a dict or None")

        self.version = version if version is not None else self.VERSION
        self.operation = operation
        self.asset = asset
        self.inputs = inputs or []
        self.outputs = outputs or []
        self.metadata = metadata
        self._id = hash_id

    @property
    def unspent_outputs(self):
        """! UnspentOutput: The outputs of this transaction, in a data
        structure containing relevant information for storing them in
        a UTXO set, and performing validation.
        """
        if self.operation == Transaction.CREATE:
            self._asset_id = self._id
        elif self.operation == Transaction.TRANSFER:
            self._asset_id = self.asset["id"]
        return (
            UnspentOutput(
                transaction_id=self._id,
                output_index=output_index,
                amount=output.amount,
                asset_id=self._asset_id,
                condition_uri=output.fulfillment.condition_uri,
            )
            for output_index, output in enumerate(self.outputs)
        )

    @property
    def spent_outputs(self):
        """! Tuple of :obj:`dict`: Inputs of this transaction. Each input
        is represented as a dictionary containing a transaction id and
        output index.
        """
        return (input_.fulfills.to_dict() for input_ in self.inputs if input_.fulfills)

    @property
    def serialized(self):
        return Transaction._to_str(self.to_dict())

    def _hash(self):
        self._id = hash_data(self.serialized)

    @classmethod
    def create(cls, tx_signers, recipients, metadata=None, asset=None):
        """! A simple way to generate a `CREATE` transaction.
        Note:
            This method currently supports the following Cryptoconditions
            use cases:
                - Ed25519
                - ThresholdSha256
            Additionally, it provides support for the following Resdb
            use cases:
                - Multiple inputs and outputs.

        @param tx_signers (:obj:`list` of :obj:`str`): A list of keys that
            represent the signers of the CREATE Transaction.
        @param recipients (:obj:`list` of :obj:`tuple`): A list of
            ([keys],amount) that represent the recipients of this
            Transaction.
        @param metadata (dict): The metadata to be stored along with the
            Transaction.
        @param asset (dict): The metadata associated with the asset that will
            be created in this Transaction.

        @return :class:`~resdb.transaction.Transaction`
        """
        if not isinstance(tx_signers, list):
            raise TypeError("`tx_signers` must be a list instance")
        if not isinstance(recipients, list):
            raise TypeError("`recipients` must be a list instance")
        if len(tx_signers) == 0:
            raise ValueError("`tx_signers` list cannot be empty")
        if len(recipients) == 0:
            raise ValueError("`recipients` list cannot be empty")
        if not (asset is None or isinstance(asset, dict)):
            raise TypeError("`asset` must be a dict or None")

        inputs = []
        outputs = []

        # generate_outputs
        for recipient in recipients:
            if not isinstance(recipient, tuple) or len(recipient) != 2:
                raise ValueError(
                    (
                        "Each `recipient` in the list must be a"
                        " tuple of `([<list of public keys>],"
                        " <amount>)`"
                    )
                )
            pub_keys, amount = recipient
            outputs.append(Output.generate(pub_keys, amount))

        # generate inputs
        inputs.append(Input.generate(tx_signers))

        return cls(cls.CREATE, {"data": asset}, inputs, outputs, metadata)

    @classmethod
    def transfer(cls, inputs, recipients, asset_id, metadata=None):
        """! A simple way to generate a `TRANSFER` transaction.
        Note:
            Different cases for threshold conditions:
            Combining multiple `inputs` with an arbitrary number of
            `recipients` can yield interesting cases for the creation of
            threshold conditions we'd like to support. The following
            notation is proposed:
            1. The index of a `recipient` corresponds to the index of
               an input:
               e.g. `transfer([input1], [a])`, means `input1` would now be
                    owned by user `a`.
            2. `recipients` can (almost) get arbitrary deeply nested,
               creating various complex threshold conditions:
               e.g. `transfer([inp1, inp2], [[a, [b, c]], d])`, means
                    `a`'s signature would have a 50% weight on `inp1`
                    compared to `b` and `c` that share 25% of the leftover
                    weight respectively. `inp2` is owned completely by `d`.

        @param inputs (:obj:`list` of :class:`~resdb.transaction.Input`): Converted `Output`s, intended to
            be used as inputs in the transfer to generate.
        @param recipients (:obj:`list` of :obj:`tuple`): A list of
            ([keys],amount) that represent the recipients of this
            Transaction.
        @param asset_id (str): The asset ID of the asset to be transferred in
            this Transaction.
        @param metadata (dict): Python dictionary to be stored along with the
            Transaction.

        @return :class:`~resdb.transaction.Transaction`
        """
        if not isinstance(inputs, list):
            raise TypeError("`inputs` must be a list instance")
        if len(inputs) == 0:
            raise ValueError("`inputs` must contain at least one item")
        if not isinstance(recipients, list):
            raise TypeError("`recipients` must be a list instance")
        if len(recipients) == 0:
            raise ValueError("`recipients` list cannot be empty")

        outputs = []
        for recipient in recipients:
            if not isinstance(recipient, tuple) or len(recipient) != 2:
                raise ValueError(
                    (
                        "Each `recipient` in the list must be a"
                        " tuple of `([<list of public keys>],"
                        " <amount>)`"
                    )
                )
            pub_keys, amount = recipient
            outputs.append(Output.generate(pub_keys, amount))

        if not isinstance(asset_id, str):
            raise TypeError("`asset_id` must be a string")

        inputs = deepcopy(inputs)
        return cls(cls.TRANSFER, {"id": asset_id}, inputs, outputs, metadata)

    def __eq__(self, other):
        try:
            other = other.to_dict()
        except AttributeError:
            return False
        return self.to_dict() == other

    def to_inputs(self, indices=None):
        """! Converts a Transaction's outputs to spendable inputs.
        Note:
            Takes the Transaction's outputs and derives inputs
            from that can then be passed into `Transaction.transfer` as
            `inputs`.
            A list of integers can be passed to `indices` that
            defines which outputs should be returned as inputs.
            If no `indices` are passed (empty list or None) all
            outputs of the Transaction are returned.

        @param indices (:obj:`list` of int): Defines which
            outputs should be returned as inputs.
        @return :obj:`list` of :class:`~resdb.transaction.
            Input`
        """
        # NOTE: If no indices are passed, we just assume to take all outputs
        #       as inputs.
        indices = indices or range(len(self.outputs))
        return [
            Input(
                self.outputs[idx].fulfillment,
                self.outputs[idx].public_keys,
                TransactionLink(self.id, idx),
            )
            for idx in indices
        ]

    def add_input(self, input_):
        """! Adds an input to a Transaction's list of inputs.
        @param input_ (:class:`~resdb.transaction.
            Input`): An Input to be added to the Transaction.
        """
        if not isinstance(input_, Input):
            raise TypeError("`input_` must be a Input instance")
        self.inputs.append(input_)

    def add_output(self, output):
        """! Adds an output to a Transaction's list of outputs.
        @param output (:class:`~resdb.transaction.
            Output`): An Output to be added to the
            Transaction.
        """
        if not isinstance(output, Output):
            raise TypeError("`output` must be an Output instance or None")
        self.outputs.append(output)

    def sign(self, private_keys):
        """! Fulfills a previous Transaction's Output by signing Inputs.
        Note:
            This method works only for the following Cryptoconditions
            currently:
                - Ed25519Fulfillment
                - ThresholdSha256
            Furthermore, note that all keys required to fully sign the
            Transaction have to be passed to this method. A subset of all
            will cause this method to fail.

        @param private_keys (:obj:`list` of :obj:`str`): A complete list of
            all private keys needed to sign all Fulfillments of this
            Transaction.
        @return :class:`~resdb.transaction.Transaction`
        """
        # TODO: Singing should be possible with at least one of all private
        #       keys supplied to this method.
        if private_keys is None or not isinstance(private_keys, list):
            raise TypeError("`private_keys` must be a list instance")

        # NOTE: Generate public keys from private keys and match them in a
        #       dictionary:
        #                   key:     public_key
        #                   value:   private_key
        def gen_public_key(private_key):
            # TODO FOR CC: Adjust interface so that this function becomes
            #              unnecessary

            # cc now provides a single method `encode` to return the key
            # in several different encodings.
            public_key = private_key.get_verifying_key().encode()
            # Returned values from cc are always bytestrings so here we need
            # to decode to convert the bytestring into a python str
            return public_key.decode()

        key_pairs = {
            gen_public_key(PrivateKey(private_key)): PrivateKey(private_key)
            for private_key in private_keys
        }

        tx_dict = self.to_dict()
        tx_dict = Transaction._remove_signatures(tx_dict)
        tx_serialized = Transaction._to_str(tx_dict)
        for i, input_ in enumerate(self.inputs):
            self.inputs[i] = self._sign_input(input_, tx_serialized, key_pairs)

        self._hash()

        return self

    @classmethod
    def _sign_input(cls, input_, message, key_pairs):
        """! Signs a single Input.
        Note:
            This method works only for the following Cryptoconditions
            currently:
                - Ed25519Fulfillment
                - ThresholdSha256.

        @param input_ (:class:`~resdb.transaction.Input`) The Input to be signed.
        @param message (str): The message to be signed
        @param key_pairs (dict): The keys to sign the Transaction with.
        """
        if isinstance(input_.fulfillment, Ed25519Sha256):
            return cls._sign_simple_signature_fulfillment(input_, message, key_pairs)
        elif isinstance(input_.fulfillment, ThresholdSha256):
            return cls._sign_threshold_signature_fulfillment(input_, message, key_pairs)
        else:
            raise ValueError(
                "Fulfillment couldn't be matched to "
                "Cryptocondition fulfillment type."
            )

    @classmethod
    def _sign_simple_signature_fulfillment(cls, input_, message, key_pairs):
        """! Signs a Ed25519Fulfillment.

        @param input_ (:class:`~resdb.transaction.Input`) The Input to be signed.
        @param message (str): The message to be signed
        @param key_pairs (dict): The keys to sign the Transaction with.
        """
        # NOTE: To eliminate the dangers of accidentally signing a condition by
        #       reference, we remove the reference of input_ here
        #       intentionally. If the user of this class knows how to use it,
        #       this should never happen, but then again, never say never.
        input_ = deepcopy(input_)
        public_key = input_.owners_before[0]
        message = sha3_256(message.encode())
        if input_.fulfills:
            message.update(
                "{}{}".format(input_.fulfills.txid, input_.fulfills.output).encode()
            )

        try:
            # cryptoconditions makes no assumptions of the encoding of the
            # message to sign or verify. It only accepts bytestrings
            input_.fulfillment.sign(
                message.digest(), base58.b58decode(key_pairs[public_key].encode())
            )
        except KeyError:
            raise KeypairMismatchException(
                "Public key {} is not a pair to "
                "any of the private keys".format(public_key)
            )
        return input_

    @classmethod
    def _sign_threshold_signature_fulfillment(cls, input_, message, key_pairs):
        """! Signs a ThresholdSha256.

        @param input_ (:class:`~resdb.transaction.Input`) The Input to be signed.
        @param message (str): The message to be signed
        @param key_pairs (dict): The keys to sign the Transaction with.
        """
        input_ = deepcopy(input_)
        message = sha3_256(message.encode())
        if input_.fulfills:
            message.update(
                "{}{}".format(input_.fulfills.txid, input_.fulfills.output).encode()
            )

        for owner_before in set(input_.owners_before):
            # TODO: CC should throw a KeypairMismatchException, instead of
            #       our manual mapping here

            # TODO FOR CC: Naming wise this is not so smart,
            #              `get_subcondition` in fact doesn't return a
            #              condition but a fulfillment

            # TODO FOR CC: `get_subcondition` is singular. One would not
            #              expect to get a list back.
            ccffill = input_.fulfillment
            subffills = ccffill.get_subcondition_from_vk(base58.b58decode(owner_before))
            if not subffills:
                raise KeypairMismatchException(
                    "Public key {} cannot be found "
                    "in the fulfillment".format(owner_before)
                )
            try:
                private_key = key_pairs[owner_before]
            except KeyError:
                raise KeypairMismatchException(
                    "Public key {} is not a pair "
                    "to any of the private keys".format(owner_before)
                )

            # cryptoconditions makes no assumptions of the encoding of the
            # message to sign or verify. It only accepts bytestrings
            for subffill in subffills:
                subffill.sign(message.digest(), base58.b58decode(private_key.encode()))
        return input_

    def inputs_valid(self, outputs=None):
        """! Validates the Inputs in the Transaction against given
        Outputs.
            Note:
                Given a `CREATE` Transaction is passed,
                dummy values for Outputs are submitted for validation that
                evaluate parts of the validation-checks to `True`.

        @param outputs (:obj:`list` of :class:`~resdb.
            transaction.Output`): A list of Outputs to check the
            Inputs against.
        @return If all Inputs are valid.
        """
        if self.operation == Transaction.CREATE:
            # NOTE: Since in the case of a `CREATE`-transaction we do not have
            #       to check for outputs, we're just submitting dummy
            #       values to the actual method. This simplifies it's logic
            #       greatly, as we do not have to check against `None` values.
            return self._inputs_valid(["dummyvalue" for _ in self.inputs])
        elif self.operation == Transaction.TRANSFER:
            return self._inputs_valid(
                [output.fulfillment.condition_uri for output in outputs]
            )
        else:
            allowed_ops = ", ".join(self.__class__.ALLOWED_OPERATIONS)
            raise TypeError("`operation` must be one of {}".format(allowed_ops))

    def _inputs_valid(self, output_condition_uris):
        """!Validates an Input against a given set of Outputs.
        Note:
            The number of `output_condition_uris` must be equal to the
            number of Inputs a Transaction has.

        @param output_condition_uris (:obj:`list` of :obj:`str`): A list of
            Outputs to check the Inputs against.
        @return If all Outputs are valid.
        """

        if len(self.inputs) != len(output_condition_uris):
            raise ValueError(
                "Inputs and " "output_condition_uris must have the same count"
            )

        tx_dict = self.to_dict()
        tx_dict = Transaction._remove_signatures(tx_dict)
        tx_dict["id"] = None
        tx_serialized = Transaction._to_str(tx_dict)

        def validate(i, output_condition_uri=None):
            """Validate input against output condition URI"""
            return self._input_valid(
                self.inputs[i], self.operation, tx_serialized, output_condition_uri
            )

        return all(validate(i, cond) for i, cond in enumerate(output_condition_uris))

    @staticmethod
    def _input_valid(input_, operation, message, output_condition_uri=None):
        """! Validates a single Input against a single Output.
        Note:
            In case of a `CREATE` Transaction, this method
            does not validate against `output_condition_uri`.

        @param input_ (:class:`~resdb.transaction.Input`) The Input to be signed.
        @param operation (str): The type of Transaction.
        @param message (str): The fulfillment message.
        @param output_condition_uri (str, optional): An Output to check the
            Input against.
        @return If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError, ASN1DecodeError, ASN1EncodeError):
            return False

        if operation == Transaction.CREATE:
            # NOTE: In the case of a `CREATE` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        message = sha3_256(message.encode())
        if input_.fulfills:
            message.update(
                "{}{}".format(input_.fulfills.txid, input_.fulfills.output).encode()
            )

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=message.digest())
        return output_valid and ffill_valid

    def to_dict(self):
        """! Transforms the object to a Python dictionary.
        @return The Transaction as an alternative serialization format.
        """
        return {
            "inputs": [input_.to_dict() for input_ in self.inputs],
            "outputs": [output.to_dict() for output in self.outputs],
            "operation": str(self.operation),
            "metadata": self.metadata,
            "asset": self.asset,
            "version": self.version,
            "id": self._id,
        }

    @staticmethod
    # TODO: Remove `_dict` prefix of variable.
    def _remove_signatures(tx_dict):
        """! Takes a Transaction dictionary and removes all signatures.
        @param (dict): tx_dict The Transaction to remove all signatures from.
        @return dict
        """
        # NOTE: We remove the reference since we need `tx_dict` only for the
        #       transaction's hash
        tx_dict = deepcopy(tx_dict)
        for input_ in tx_dict["inputs"]:
            # NOTE: Not all Cryptoconditions return a `signature` key (e.g.
            #       ThresholdSha256), so setting it to `None` in any
            #       case could yield incorrect signatures. This is why we only
            #       set it to `None` if it's set in the dict.
            input_["fulfillment"] = None
        return tx_dict

    @staticmethod
    def _to_hash(value):
        return hash_data(value)

    @property
    def id(self):
        return self._id

    def to_hash(self):
        return self.to_dict()["id"]

    @staticmethod
    def _to_str(value):
        return serialize(value)

    # TODO: This method shouldn't call `_remove_signatures`
    def __str__(self):
        tx = Transaction._remove_signatures(self.to_dict())
        return Transaction._to_str(tx)

    @staticmethod
    def get_asset_id(transactions):
        """! Get the asset id from a list of :class:`~.Transactions`.
        This is useful when we want to check if the multiple inputs of a
        transaction are related to the same asset id.
        Args:
            @param transactions (:obj:`list` of :class:`~resdb.transaction.Transaction`):
                A list of Transactions.
                Usually input Transactions that should have a matching
                asset ID.
            @return ID of the asset.
            @exception If the inputs are related to different assets.
        """

        if not isinstance(transactions, list):
            transactions = [transactions]

        # create a set of the transactions' asset ids
        asset_ids = {
            tx.id if tx.operation == Transaction.CREATE else tx.asset["id"]
            for tx in transactions
        }

        # check that all the transasctions have the same asset id
        if len(asset_ids) > 1:
            raise AssetIdMismatch(
                (
                    "All inputs of all transactions passed"
                    " need to have the same asset id"
                )
            )
        return asset_ids.pop()

    @staticmethod
    def validate_id(tx_body):
        """! Validate the transaction ID of a transaction
        @param tx_body (dict): The Transaction to be transformed.
        """
        # NOTE: Remove reference to avoid side effects
        tx_body = deepcopy(tx_body)
        try:
            proposed_tx_id = tx_body["id"]
        except KeyError:
            raise InvalidHash("No transaction id found!")

        tx_body["id"] = None

        tx_body_serialized = Transaction._to_str(tx_body)
        valid_tx_id = Transaction._to_hash(tx_body_serialized)

        if proposed_tx_id != valid_tx_id:
            err_msg = (
                "The transaction's id '{}' isn't equal to "
                "the hash of its body, i.e. it's not valid."
            )
            raise InvalidHash(err_msg.format(proposed_tx_id))

    @classmethod
    def from_dict(cls, tx, skip_schema_validation=True):
        """! Transforms a Python dictionary to a Transaction object.
        @param tx_body (dict): The Transaction to be transformed.
        @return :class:`~resdb.transaction.Transaction`
        """
        inputs = [Input.from_dict(input_) for input_ in tx["inputs"]]
        outputs = [Output.from_dict(output) for output in tx["outputs"]]

        if not skip_schema_validation:
            cls.validate_id(tx)
            cls.validate_schema(tx)
        return cls(
            tx["operation"],
            tx["asset"],
            inputs,
            outputs,
            tx["metadata"],
            tx["version"],
            hash_id=tx["id"],
        )

    @classmethod
    def from_db(cls, resdb, tx_dict_list):
        """! Helper method that reconstructs a transaction dict that was returned
        from the database. It checks what asset_id to retrieve, retrieves the
        asset from the asset table and reconstructs the transaction.


        @param resdb An instance of ResDB used to perform database queries.
        @param tx_dict_list (:list:`dict` or :obj:`dict`): The transaction dict or
            list of transaction dict as returned from the database.

        @return :class:`~Transaction`

        """
        return_list = True
        if isinstance(tx_dict_list, dict):
            tx_dict_list = [tx_dict_list]
            return_list = False

        tx_map = {}
        tx_ids = []
        for tx in tx_dict_list:
            tx.update({"metadata": None})
            tx_map[tx["id"]] = tx
            tx_ids.append(tx["id"])

        assets = list(resdb.get_assets(tx_ids))
        for asset in assets:
            if asset is not None:
                tx = tx_map[asset["id"]]
                del asset["id"]
                tx["asset"] = asset

        tx_ids = list(tx_map.keys())
        metadata_list = list(resdb.get_metadata(tx_ids))
        for metadata in metadata_list:
            tx = tx_map[metadata["id"]]
            tx.update({"metadata": metadata.get("metadata")})

        if return_list:
            tx_list = []
            for tx_id, tx in tx_map.items():
                tx_list.append(cls.from_dict(tx))
            return tx_list
        else:
            tx = list(tx_map.values())[0]
            return cls.from_dict(tx)

    type_registry = {}

    @staticmethod
    def register_type(tx_type, tx_class):
        Transaction.type_registry[tx_type] = tx_class

    def resolve_class(operation):
        """! For the given `tx` based on the `operation` key return its implementation class"""

        create_txn_class = Transaction.type_registry.get(Transaction.CREATE)
        return Transaction.type_registry.get(operation, create_txn_class)

    @classmethod
    def validate_schema(cls, tx):
        # TODO
        pass

    def validate_transfer_inputs(self, resdb, current_transactions=[]):
        # store the inputs so that we can check if the asset ids match
        input_txs = []
        input_conditions = []
        for input_ in self.inputs:
            input_txid = input_.fulfills.txid

            input_tx = resdb.get_transaction(input_txid)

            if input_tx is None:
                for ctxn in current_transactions:
                    if ctxn.id == input_txid:
                        input_tx = ctxn

            if input_tx is None:
                raise InputDoesNotExist("input `{}` doesn't exist".format(input_txid))

            spent = resdb.get_spent(
                input_txid, input_.fulfills.output, current_transactions
            )
            if spent:
                raise DoubleSpend("input `{}` was already spent".format(input_txid))

            output = input_tx.outputs[input_.fulfills.output]
            input_conditions.append(output)
            input_txs.append(input_tx)

        # Validate that all inputs are distinct
        links = [i.fulfills.to_uri() for i in self.inputs]
        if len(links) != len(set(links)):
            raise DoubleSpend('tx "{}" spends inputs twice'.format(self.id))

        # validate asset id
        asset_id = self.get_asset_id(input_txs)
        if asset_id != self.asset["id"]:
            raise AssetIdMismatch(
                (
                    "The asset id of the input does not"
                    " match the asset id of the"
                    " transaction"
                )
            )

        input_amount = sum(
            [input_condition.amount for input_condition in input_conditions]
        )
        output_amount = sum(
            [output_condition.amount for output_condition in self.outputs]
        )

        if output_amount != input_amount:
            raise AmountError(
                (
                    "The amount used in the inputs `{}`"
                    " needs to be same as the amount used"
                    " in the outputs `{}`"
                ).format(input_amount, output_amount)
            )

        if not self.inputs_valid(input_conditions):
            raise InvalidSignature("Transaction signature is invalid.")

        return True
