'use strict'
var AstWalker = require('../util/astWalker')

/**
  * return all contract definitions of the given @astList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @return {Object} - returns a mapping from AST node ids to AST nodes for the contracts
  */
function extractContractDefinitions (sourcesList) {
  var ret = {
    contractsById: {},
    contractsByName: {}
  }
  var walker = new AstWalker()
  walker.walkAstList(sourcesList, { 'ContractDefinition': function (node) {
    ret.contractsById[node.id] = node
    ret.contractsByName[node.attributes.name] = node
    return false
  }})
  return ret
}

/**
  * returns the linearized base contracts of the contract @arg id
  *
  * @param {Int} id - contract id to resolve
  * @param {Map} contracts  - all contracts defined in the current context
  * @return {Array} - array of base contracts in derived to base order as AST nodes.
  */
function getLinearizedBaseContracts (id, contractsById) {
  return contractsById[id].attributes.linearizedBaseContracts.map(function (id) { return contractsById[id] })
}

/**
  * return state var and type definition of the given contract
  *
  * @param {String} contractName - contract for which state var should be resolved
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @param {Object} [contracts] - map of contract definitions (contains contractsById, contractsByName)
  * @return {Object} - return an object containing: stateItems - list of all the children node of the @arg contractName
  *                                                 stateVariables - list of all the variable declaration of the @arg contractName
  */
function extractStateDefinitions (contractName, sourcesList, contracts) {
  if (!contracts) {
    contracts = extractContractDefinitions(sourcesList)
  }
  var node = contracts.contractsByName[contractName]
  if (node) {
    var stateItems = []
    var stateVar = []
    var baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById)
    baseContracts.reverse()
    for (var k in baseContracts) {
      var ctr = baseContracts[k]
      for (var i in ctr.children) {
        var item = ctr.children[i]
        stateItems.push(item)
        if (item.name === 'VariableDeclaration') {
          stateVar.push(item)
        }
      }
    }
    return {
      stateDefinitions: stateItems,
      stateVariables: stateVar
    }
  }
  return null
}

/**
  * return state var and type definition of all the contracts from the given @args sourcesList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @return {Object} - returns a mapping between contract name and contract state
  */
function extractStatesDefinitions (sourcesList) {
  var contracts = extractContractDefinitions(sourcesList)
  var ret = {}
  for (var contract in contracts.contractsById) {
    var name = contracts.contractsById[contract].attributes.name
    ret[name] = extractStateDefinitions(name, sourcesList, contracts)
  }
  return ret
}

module.exports = {
  extractStatesDefinitions: extractStatesDefinitions,
  extractStateDefinitions: extractStateDefinitions,
  extractContractDefinitions: extractContractDefinitions,
  getLinearizedBaseContracts: getLinearizedBaseContracts
}

@@ -2614,32 +2614,136 @@
  root AST node)%0A
+  * @param %7BObject%7D %5Bcontracts%5D - map of contract definitions (contains contractsById, contractsByName)%0A
   * @return %7BObj
@@ -2859,25 +2859,54 @@
 rcesList
-) %7B%0A  var
+, contracts) %7B%0A  if (!contracts) %7B%0A   
  contrac
@@ -2950,16 +2950,20 @@
 esList)%0A
+  %7D%0A
   var re

add optional param