// adopted from: https://github.com/jonschlinkert/expand
// Copyright (c) 2015, Jon Schlinkert (MIT)

var kindOf = require('../lang/kindOf')
var look   = require('../object/look')

// Curried function:
// var expand = require('expand') or require('expand')()
// var fn = expand({regex: /abc/})
// fn('{{a}}', {a: 'apple'}) or expand('{{a}}', {a: 'apple'})

function expand (opts) {
  opts = opts || {}
  var regex = opts.regex || /\{\{([^\}]+)\}\}/

  function resolve (val, data) {
    data = data || val

    switch (kindOf(val)) {
      case 'array'  :
      case 'object' : return resolveObject(val, data)
      case 'string' : return resolveString(val, data)
      default       : return val
    }
  }

  function resolveObject (obj, data) {
    Object.keys(obj).forEach(function (key, idx, arr) {
      obj[key] = resolve(obj[key], data)
    })

    return obj
  }

  function resolveString (str, data) {
    var m

    while ((m = regex.exec(str))) {
      var orig = str
      var prop = (m[1] || m[2] || '').trim()
      var match = m[0]

      if (!match) return str

      var len = match.length
      var i = m.index

      var val = match

      if (/[()]/.test(prop)) {
        val = resolveFunc(prop, data)
      } else {
        val = look(data, prop)
      }

      // if no value was retured from `look` or `resolveFunc`,
      // reset the value to `match`
      if (val == null) val = match

      if (typeof val === 'object') {
        // if the value is an object, recurse to resolve
        // templates in the keys and values of the object
        val = resolve(val, data)
      } else if (typeof val !== 'function') {
        // ensure we have a string. numbers are the most
        // likely thing to blow this up at this point
        val = val.toString()
      }

      if (typeof val === 'function') return val.bind(data)

      // could be an array, object, etc. if so, just
      // break and return the value. we could add one
      // more `resolve` here if there is a reason to
      if (typeof val !== 'string') {
        str = val
        break
      }

      var head = str.slice(0, i)
      var tail = str.slice(i + len)

      str = head + val + tail
      if (str === orig) break
    }

    return str
  }

  function resolveFunc (prop, data) {
    // This is a hack!! this does not cover all cases as with
    // https://github.com/jonschlinkert/expand. But then again,
    // I have no to little use calling functions in this type
    // of situation
    var firstparens = prop.indexOf('(')
    var lastparens = prop.indexOf(')')
    var expr = prop.slice(0, firstparens)
    var exprParam = prop.slice(firstparens + 1, lastparens)

    return typeof data[expr] === 'function'
      ? data[expr](data[exprParam])
      : resolve('{{' + expr + '}}', data)(exprParam)
  }

  return resolve
}

module.exports = expand

@@ -177,17 +177,25 @@
 k')%0A%0A// 
-C
+Removed c
 urried f
@@ -240,127 +240,47 @@
 nd')
- or require('expand')()%0A// var fn = expand(%7Bregex: /abc/%7D)%0A// fn('%7B%7Ba%7D%7D', %7Ba: 'apple'%7D) or expand('%7B%7Ba%7D%7D', %7Ba: 'apple'%7D
+%0A// expand('%7B%7Ba%7D%7D', %7Ba: 'apple'%7D, regex
 )%0A%0Af
@@ -295,16 +295,27 @@
 expand (
+val, data, 
 opts) %7B%0A
@@ -327,65 +327,25 @@
 s = 
-opts %7C%7C %7B%7D%0A  var regex = opts.regex %7C%7C /%5C%7B%5C%7B(%5B%5E%5C%7D%5D+)%5C%7D%5C%7D/
+defaultOpts(opts)
 %0A%0A  
@@ -647,56 +647,35 @@
     
-Object.keys(obj).forEach(function
+var key%0A    for
  (key
-,
  i
-dx, arr
+n obj
 ) %7B%0A
@@ -679,16 +679,45 @@
  %7B%0A     
+ if (obj.hasOwnProperty(key))
  obj%5Bkey
@@ -749,17 +749,16 @@
 a)%0A    %7D
-)
 %0A%0A    re
@@ -802,32 +802,53 @@
 g (str, data) %7B%0A
+    var regex = opts%0A
     var m%0A%0A    w
@@ -2749,16 +2749,169 @@
  resolve
+(val, data)%0A%7D%0A%0Afunction defaultOpts (opts) %7B%0A  // in the event options expand%0A  // this functin exists.%0A  opts = opts %7C%7C /%5C%7B%5C%7B(%5B%5E%5C%7D%5D+)%5C%7D%5C%7D/%0A  return opts
 %0A%7D%0A%0Amodu

update string/expander.js -- reversion