/* Copyright (c) 2014, Andrew Hart <hello@andrewfhart.com>
 *
 * Licensed 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.
 */

'use strict';

var bitcore  = require('bitcore'),
    MarkerOutput = require('./MarkerOutput');

/**
 * TransactionBuilder
 *
 * Provides methods for constructing Open Assets transactions
**/

/**
 * Constructor
 * @param int  dustAmount  The minimum allowed output data
**/
var TransactionBuilder = function (dustAmount) {
  self.dustAmount = dustAmount;
};

/**
 * Create a transaction for issuing an asset
 * @param TransferParameter issuanceSpec  The parameters of the issuance
 * @param Buffer            metadata      The metadata to be embedded in the transaction
 * @param int               fees          The fees to include in the transaction
 * @return  Transaction     an unsigned transaction for issuing an asset
**/
TransactionBuilder.prototype.issue = function (issuanceSpec, metadata, fees) {
  var inputs, totalAmount, outputInfo, builder, tx;

  // Returns an object containing two keys: inputs, totalAmount
  outputInfo = _collectUncoloredOutputs(
    issuanceSpec.unspentOutputs, 2 * self.dustAmount + fees);

  builder = (new bitcore.TransactionBuilder({
    feeSat: fees,
    amountSat: outputInfo.totalAmount
  }))
    .setUnspent('foo')
    .setOutputs('foo');



};

TransactionBuilder.prototype.transfer = function (transferSpec, fees) {

};

TransactionBuilder.prototype.transferBitcoin = function (transferSpec, fees) {

};

TransactionBuilder.prototype.transferAssets = function (assetId, transferSpec, btcChangeScript, fees) {

};

TransactionBuilder.prototype.bitcoinAssetSwap = function (btcTransferSpec, assetId, assetTransferSpec, fees) {

};

TransactionBuilder.prototype.assetAssetSwap = function (asset1Id, asset1TransferSpec, asset2Id, asset2TransferSpec, fees) {

};

/**
 * Return a list of uncolored outputs for the specified amount
 * @param  array(SpendableOutput) unspentOutputs  The list of available outputs
 * @param  int                    amount          The amount to collect
 * @return Object(inputs:array(SpendableOutput),totalAmount:int)
**/
TransactionBuilder.prototype._collectUncoloredOutputs = function(unspentOutputs, amount) {
  var totalAmount = 0, result = [];

  unspentOutputs.forEach(function (spendableOutput) {
    if (spendableOutput.output.assetId == null) {
      result.push(spendableOutput);
      totalAmount += spendableOutput.output.value);
    }

    if (totalAmount >= amount) {
      return {
        inputs: result,
        totalAmount: totalAmount
      };
    }

    throw new Error("Insufficient funds");
  });
};

/**
 * Create an uncolored output
 * @param Buffer   script  The output script
 * @param int      value   The satoshi value of the output
 * @return Object  An object representing the uncolored output
**/
TransactionBuilder.prototype._getUncoloredOutput = function (script, value) {
  if (value < this.dustAmount) {
    throw Error('The value of the output would be too small, and the output would be considered "dust"');
  }

  return {v: value, s: script};
};

TransactionBuilder.prototype._collecteColoredOutputs = function (unspentOutputs, assetId, assetQuantity) {

};

/**
 * Create a colored output
 * @param Buffer   script  The output script
 * @return Object  An object representing the colored output
**/
TransactionBuilder.prototype._getColoredOutput = function (script) {
  return {v: this.dustAmount, s: script};
};

/** 
 * Create a marker output
 *
 * @param array(int)  assetQuantities  The asset quantity list
 * @param Buffer      metadata         The metadata contained in the output
 * @return Object     An object representing the marker output
**/
TransactionBuilder.prototype._getMarkerOutput = function (assetQuantities, metadata) {
  var output  = new MarkerOutput(assetQuantities, metadata),
      payload = mo.serializePayload(),
      script  = mo.buildScript(payload);
  return {v: 0, s: script}; // Marker output has value 0 satoshis
};

@@ -3569,24 +3569,399 @@
 cript%7D;%0A%7D;%0A%0A
+/**%0A * Return a list of colored outputs for the specified quantity%0A * @param array(SpendableOutput)  unspentOutputs  The list of available outputs%0A * @param Buffer                  assetId         The ID of the asset to collect%0A * @param int                     quantity        The asset quantity to collect%0A * @return Object(outputs:array(SpendableOutput),quantity:int)%0A**/%0A
 TransactionB
@@ -3985,17 +3985,16 @@
 _collect
-e
 ColoredO
@@ -4050,24 +4050,459 @@
 Quantity) %7B%0A
+  var totalQuantity = 0,%0A      result = %5B%5D;%0A%0A  unspentOutputs.forEach(function (spendableOutput) %7B%0A    if (spendableOutput.output.assetId == assetId) %7B%0A      result.push(spendableOutput);%0A      totalQuantity += spendableOutput.output.assetQuantity;%0A    %7D%0A%0A    if (totalQuantity %3E= assetQuantity) %7B%0A      return %7Boutputs: result, quantity: totalQuantity%7D;%0A    %7D%0A  %7D);%0A%0A  throw new Error(%22An insufficient amount of assets is available%22);
 %0A%7D;%0A%0A/**%0A * 

Implement TransactionBuilder::_collectColoredOutputs