/* 
 * UTXO.java
 * 
 * This class represents an unspent transaction output (UTXO)
 */

import java.util.Arrays;

public class UTXO implements Comparable<UTXO> {
   
   // Hash of the transaction from which this UTXO originates
   private byte[] txHash;
   
   // Index of the corresponding output in said transaction
   private int index;  
   
   // Creates a new UTXO corresponding to the output with index <index> in the 
   // transaction whose hash is <txHash>
   public UTXO(byte[] txHash, int index) {
      this.txHash = Arrays.copyOf(txHash, txHash.length);
      this.index = index;
   }
   
   // Returns the transaction hash of this UTXO
   public byte[] getTxHash() {
      return txHash;
   }
   
   // Returns the index of this UTXO
   public int getIndex() {
      return index;
   }
   
   // Compares this UTXO to the one specified by <other>, considering them equal if 
   // they have <txHash> arrays with equal contents and equal <index> values
   public boolean equals(Object other) {
      if (other == null) {
         return false;
      }
      if (getClass() != other.getClass()) {
         return false;
      }
      
      UTXO utxo = (UTXO) other;
      byte[] hash = utxo.txHash;
      int in = utxo.index;
      if (hash.length != txHash.length || index != in)
         return false;
      for (int i = 0; i < hash.length; i++) {
         if (hash[i] != txHash[i])
            return false;
      }
      return true;
   }
   
   // Simple implementation of a UTXO hashCode that respects equality of UTXOs
   // (i.e. utxo1.equals(utxo2) => utxo1.hashCode() == utxo2.hashCode())
   public int hashCode() {
      int hash = 1;
      hash = hash * 17 + index;
      hash = hash * 31 + Arrays.hashCode(txHash);
      return hash;
   }
   
   // Compares this UTXO to the one specified by <utxo>
   public int compareTo(UTXO utxo) {
      byte[] hash = utxo.txHash;
      int in = utxo.index;
      if (in > index) 
         return -1;
      else if (in < index)
         return 1;
      else {
         int len1 = txHash.length;
         int len2 = hash.length;
         if (len2 > len1)
            return -1;
         else if (len2 < len1)
            return 1;
         else {
            for (int i = 0; i < len1; i++) {
               if (hash[i] > txHash[i])
                  return -1;
               else if (hash[i] < txHash[i])
                  return 1;
            }
            return 0;
         }
      }
   }
}
