MINE_REWARD_VALUE = 25.0
REGISTRATION_REWARD_VALUE = 50.0
NORMAL = 0
REWARD = 1

from helpers import SignatureHelper as Signature
from helpers import UtilityHelper as utilityHelper

class Tx:
    def __init__(self, type = NORMAL):
        
        self.type = type
        self.inputs = []
        self.outputs = []
        self.sigs = []
        self.reqd = []

    def add_input(self, from_addr, amount):
        self.inputs.append((from_addr, amount))

    def add_output(self, to_addr, amount):
        self.outputs.append((to_addr, amount))

    def add_reqd(self, addr):
        self.reqd.append(addr)

    def sign(self, private):
        ser = Signature.privateBytesToKey(private)
        message = self.__gather()
        newsig = Signature.sign(message, ser)
        self.sigs.append(newsig)
               
    def is_valid(self):

        if self.type == REWARD:
            if len(self.inputs)!=0 and len(self.outputs)!=1:
                return False
            return True
        
        else:
            total_in = 0
            total_out = 0
            message = self.__gather()
            for addr,amount in self.inputs:
                found = False
                for s in self.sigs:
                    if Signature.verify(message, s, addr):
                        found = True
                if not found:
                    return False
                if amount < 0:
                    return False
                total_in = total_in + amount
            for addr in self.reqd:
                found = False
                for s in self.sigs:
                    if Signature.verify(message, s, addr):
                        found = True
                if not found:
                    return False
            for addr,amount in self.outputs:
                if amount < 0:
                    return False
                total_out = total_out + amount

            if total_out > total_in:
                return False        
            return True

    def __gather(self):
        data=[]
        data.append(self.inputs)
        data.append(self.outputs)
        data.append(self.reqd)
        return data

    def __repr__(self):

        repr_str = "INPUTS:\n"
        for addr, amt in self.inputs:
            repr_str = repr_str + str(amt) + "from" + str(addr) + "\n"

        repr_str += "OUTPUTS:\n"
        for addr, amt in self.outputs:
            repr_str = repr_str + str(amt) + "to" + str(addr) + "\n"

        repr_str += "EXTRA REQUIRED SIGNATURES:\n"     
        for req_sig in self.reqd:
            repr_str = repr_str + str(req_sig) + "\n"

        repr_str += "SIGNATURES:\n"     
        for sig in self.sigs:
            repr_str = repr_str + str(sig) + "\n"

        repr_str += "END\n"
        
        return repr_str
    
    def createTransaction(self, public_ser, private_ser, amount, fee, recipient, reqd = None, type = NORMAL):
        self.add_input(public_ser, amount + fee)
        self.add_output(recipient, amount)
        self.type = type
        if reqd != None:
            self.add_reqd(reqd)
        self.sign(private_ser)

    def createRewardTransaction(self, public_ser, private_ser, type, fee = 0):
        if type == "MINE":
            self.add_output(public_ser, MINE_REWARD_VALUE + fee)
        else:
            self.add_output(public_ser, REGISTRATION_REWARD_VALUE)
        self.type = REWARD
        self.sign(private_ser)

