"""The implementation of HEP Proof protocol

"""

__copyright__ = """ Copyright (c) 2019 Newton Foundation. All rights reserved."""
__version__ = '1.0'
__author__ = 'xiawu@zeuux.org'

import logging

from hep_rest_api import models
from hep_rest_api.scenarios import BaseHelper

logger = logging.getLogger(__name__)


class Order(object):
    """docstring for Order"""

    def __init__(self,
                 order_number,  # The identifier of the order.
                 description,  # The description of the order.
                 total_price,  # The total price of the order.
                 price_currency,  # The price currency  of the order.
                 seller,  # The order seller's NEWID.
                 customer,  # The order customer's NEWID.
                 broker='',  # The order broker's NEWID.
                 chain_txid='',  # The transaction id of the order.
                 ):
        self.order_number = order_number
        self.description = description
        self.total_price = total_price
        self.price_currency = price_currency
        self.seller = seller
        self.customer = customer
        self.broker = broker
        self.chain_txid = chain_txid
        self.order_items = []

    def add_order_item(self,
                       order_item_number,  # The identifier of the order item.
                       order_item_quantity,
                       # The number of the item ordered. If the property is not set, assume the quantity is one.
                       price,  # The order item's price
                       price_currency,  # The symbol of fiat or digital token, such as USD, CNY, NEW,BTC,ETH.
                       thing_name,  # The thing name such as product or service name.
                       thing_id,  # The thing id such as sku, ISBN.
                       thing_type='product',  # The thing type such as product or service.
                       ):
        self.order_items.append({
            'order_item_number': order_item_number,
            'order_item_quantity': order_item_quantity,
            'price': price,
            'price_currency': price_currency,
            'ordered_item': {
                'name': thing_name,
                'thing_id': thing_id,
                'thing_type': thing_type,
            },
        })

    def to_dict(self):
        return {
            'order_number': self.order_number,
            'description': self.description,
            'total_price': self.total_price,
            'price_currency': self.price_currency,
            'seller': self.seller,
            'customer': self.customer,
            'broker': self.broker,
            'chain_txid': self.chain_txid,
            'order_items': self.order_items
        }


class OrderProof(object):
    def __init__(self,
                 total_price,
                 # The amount of fiat or digital token, unit is the minimum unit of given fiat or digital token.
                 price_currency,  # The symbol of fiat or digital token, such as USD, RMB, NEW,BTC,ETH.
                 submitter,  # The submitter's NewID
                 proof_type='order',  # The proof type which value is "order".
                 ):
        self.price_currency = price_currency
        self.total_price = total_price
        self.submitter = submitter
        self.proof_type = proof_type
        self.orders = []

    def add_order(self,
                  order,  # The order item.
                  ):
        self.orders.append(order)

    def to_dict(self):
        return {
            'price_currency': self.price_currency,
            'total_price': self.total_price,
            'submitter': self.submitter,
            'proof_type': self.proof_type,
            'orders': self.orders
        }


class ProofHelper(BaseHelper):
    def generate_proof_request(self,
                               content,
                               uuid=None):
        """Generate the payment request
        
        :param str dapp_id: The DApp ID
        :param dict content: The content. it can be generated by OrderProof utility.
        :param str action: The request action name
        :param str uuid: The request uuid for desktop-browser. optional.
        :rtype: dict
        :return: The request information including signature
        """
        if not uuid:
            raise AttributeError(
                "uuid can not be None"
            )
        if not content:
            raise AttributeError(
                "content can not be None"
            )
        data = {
            'action': self.action_auth_proof,
            'uuid': uuid,
            'content': content,
            'dapp_id': self.dapp_id
        }
        sign_data = self.generate_sign_data(data)
        hmac_data = self.sign_hmac(sign_data)
        final_data = self.sign_secp256r1(hmac_data)
        # start request
        proofs = models.CreateProofRequest(**final_data)
        auth_response = self.api_client.rest_proofs_create(proofs, self.api_version)
        return auth_response

    def generate_qrcode_string(self, proof_hash):
        """Generate the hep-based scheme string string for QRCode 
        
        :param dict proof_hash: The proof request hash
        :rtype: str
        :return: The QRcode string
        """
        protocol = self.base_parameters.get('protocol')
        action = self.action_auth_proof
        qrcode_str = "%s://%s/?action=%s&proof_hash=%s" % (protocol.lower(), self.dapp_id, action, proof_hash)
        return qrcode_str

    def validate_proof_callback(self, data):
        """Validate the response of proof callback sent by end users such as NewPay users 
        
        :param dict data: The callback data
        :rtype: bool
        :return: True if valid data, otherwise False
        """
        return self.validate_r1_data(data)

    def get_status_of_proofs(self, proof_hashes):
        """Get the status of given proof_hashes.eg: SUBMIT, CONFIRM, PROCESSING, PART_CANCELED, CANCELED

        :param proof_hashes: list
        :rtype: RetrieveProofReceiptsResponse
        :return: The list of proofs status
        """
        params = {
            'proof_hashes': proof_hashes
        }
        sign_data = self.generate_sign_data(params)
        hmac_data = self.sign_hmac(sign_data)
        proof_request = models.RetrieveProofReceiptsRequest(**hmac_data)
        response = self.api_client.rest_proofs_receipts_create(body=proof_request, api_version=self.api_version)
        return response
