#!/usr/bin/env python
# coding=utf-8

from base64 import b64decode

import json
import sys

from ....cli import click
from ....providers.bytom.solver import (
    FundSolver, ClaimSolver, RefundSolver
)
from ....providers.bytom.signature import (
    FundSignature, ClaimSignature, RefundSignature
)
from ....providers.bytom.utils import is_transaction_raw
from ....providers.config import bytom
from ....exceptions import TransactionRawError
from ....utils import clean_transaction_raw

# Bytom config
bytom = bytom()


@click.command("sign", options_metavar="[OPTIONS]",
               short_help="Select Bytom transaction raw signer.")
@click.option("-xp", "--xprivate", type=str, required=True, help="Set Bytom xprivate key.")
@click.option("-r", "--raw", type=str, required=True, help="Set Bytom unsigned transaction raw.")
@click.option("-b", "--bytecode", type=str, default=None,
              help="Set Bytom witness HTLC bytecode.  [default: None]", show_default=True)
@click.option("-sk", "--secret-key", type=str, default=None,
              help="Set secret key.  [default: None]", show_default=True)
@click.option("-ac", "--account", type=int, default=1,
              help="Set Bytom derivation from account.", show_default=True)
@click.option("-ch", "--change", type=bool, default=False,
              help="Set Bytom derivation from change.", show_default=True)
@click.option("-ad", "--address", type=int, default=1,
              help="Set Bytom derivation from address.", show_default=True)
@click.option("-p", "--path", type=str, default=None,
              help="Set Bytom derivation from path.  [default: None]", show_default=True)
@click.option("-i", "--indexes", type=list, default=None,
              help="Set Bytom derivation from indexes.  [default: None]", show_default=True)
def sign(xprivate, raw, bytecode, secret_key, account, change, address, path, indexes):

    try:
        if not is_transaction_raw(transaction_raw=raw):
            raise TransactionRawError("Invalid Bitcoin unsigned transaction raw.")

        transaction_raw = clean_transaction_raw(raw)
        decoded_transaction_raw = b64decode(transaction_raw.encode())
        loaded_transaction_raw = json.loads(decoded_transaction_raw.decode())

        if loaded_transaction_raw["type"] == "bytom_fund_unsigned":
            # Fund HTLC solver
            fund_solver = FundSolver(
                xprivate_key=xprivate,
                account=account, change=change, address=address,
                path=path, indexes=indexes
            )
            # Fund signature
            fund_signature = FundSignature(
                network=loaded_transaction_raw["network"]
            )
            fund_signature.sign(
                transaction_raw=raw, solver=fund_solver
            )
            click.echo(fund_signature.transaction_raw())

        elif loaded_transaction_raw["type"] == "bytom_claim_unsigned":
            if secret_key is None:
                click.echo(click.style("Error: {}").format(
                    "Secret key is required for claim, use -s or --secret_key \"Hello Meheret!\""
                ), err=True)
                sys.exit()
            if bytecode is None:
                click.echo(click.style("Error: {}").format(
                    "Witness bytecode is required for claim, use -b or --bytecode \"016...\""
                ), err=True)
                sys.exit()

            # Claim HTLC solver
            claim_solver = ClaimSolver(
                xprivate_key=xprivate, secret_key=secret_key, bytecode=bytecode,
                account=account, change=change, address=address,
                path=path, indexes=indexes
            )
            # Claim signature
            claim_signature = ClaimSignature(
                network=loaded_transaction_raw["network"]
            )
            claim_signature.sign(
                transaction_raw=raw, solver=claim_solver
            )
            click.echo(claim_signature.transaction_raw())
    
        elif loaded_transaction_raw["type"] == "bytom_refund_unsigned":
            if bytecode is None:
                click.echo(click.style("Error: {}").format(
                    "Witness bytecode is required for claim, use -b or --bytecode \"016...\""
                ), err=True)
                sys.exit()

            # Refunding HTLC solver
            refund_solver = RefundSolver(
                xprivate_key=xprivate, bytecode=bytecode,
                account=account, change=change, address=address,
                path=path, indexes=indexes
            )
            # Refund signature
            refund_signature = RefundSignature(
                network=loaded_transaction_raw["network"]
            )
            refund_signature.sign(
                transaction_raw=raw, solver=refund_solver
            )
            click.echo(refund_signature.transaction_raw())
        else:
            click.echo(click.style("Error: {}")
                       .format("Unknown Bytom unsigned transaction raw type."), err=True)
            sys.exit()
    except Exception as exception:
        click.echo(click.style("Error: {}")
                   .format(str(exception)), err=True)
        sys.exit()
