/**

* lodash (Custom Build) <https://lodash.com/>
* Build: `lodash modularize exports="npm" -o ./`
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/

/** Used as the `TypeError` message for “Functions” methods. */ var FUNC_ERROR_TEXT = 'Expected a function';

/** Used as the internal argument placeholder. */ var PLACEHOLDER = 'lodash_placeholder';

/** Used to compose bitmasks for function metadata. */ var BIND_FLAG = 1,

BIND_KEY_FLAG = 2,
CURRY_BOUND_FLAG = 4,
CURRY_FLAG = 8,
CURRY_RIGHT_FLAG = 16,
PARTIAL_FLAG = 32,
PARTIAL_RIGHT_FLAG = 64,
ARY_FLAG = 128,
REARG_FLAG = 256,
FLIP_FLAG = 512;

/** Used as references for various `Number` constants. */ var INFINITY = 1 / 0,

MAX_SAFE_INTEGER = 9007199254740991,
MAX_INTEGER = 1.7976931348623157e+308,
NAN = 0 / 0;

/** Used to associate wrap methods with their bit flags. */ var wrapFlags = [

['ary', ARY_FLAG],
['bind', BIND_FLAG],
['bindKey', BIND_KEY_FLAG],
['curry', CURRY_FLAG],
['curryRight', CURRY_RIGHT_FLAG],
['flip', FLIP_FLAG],
['partial', PARTIAL_FLAG],
['partialRight', PARTIAL_RIGHT_FLAG],
['rearg', REARG_FLAG]

];

/** `Object#toString` result references. */ var funcTag = '[object Function]',

genTag = '[object GeneratorFunction]',
symbolTag = '[object Symbol]';

/**

* Used to match `RegExp`
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
*/

var reRegExpChar = /[\^$.*+?()[]{}|]/g;

/** Used to match leading and trailing whitespace. */ var reTrim = /^s+|s+$/g;

/** Used to match wrap detail comments. */ var reWrapComment = /{(?:n/* [wrapped with .+] */)?n?/,

reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
reSplitDetails = /,? & /;

/** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-]0x[0-9a-f]$/i;

/** Used to detect binary string values. */ var reIsBinary = /^0b+$/i;

/** Used to detect host constructors (Safari). */ var reIsHostCtor = /^[object .+?Constructor]$/;

/** Used to detect octal string values. */ var reIsOctal = /^0o+$/i;

/** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|d*)$/;

/** Built-in method references without a dependency on `root`. */ var freeParseInt = parseInt;

/** Detect free variable `global` from Node.js. */ var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */ var root = freeGlobal || freeSelf || Function('return this')();

/**

* A faster alternative to `Function#apply`, this function invokes `func`
* with the `this` binding of `thisArg` and the arguments of `args`.
*
* @private
* @param {Function} func The function to invoke.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} args The arguments to invoke `func` with.
* @returns {*} Returns the result of `func`.
*/

function apply(func, thisArg, args) {

switch (args.length) {
  case 0: return func.call(thisArg);
  case 1: return func.call(thisArg, args[0]);
  case 2: return func.call(thisArg, args[0], args[1]);
  case 3: return func.call(thisArg, args[0], args[1], args[2]);
}
return func.apply(thisArg, args);

}

/**

* A specialized version of `_.forEach` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/

function arrayEach(array, iteratee) {

var index = -1,
    length = array ? array.length : 0;

while (++index < length) {
  if (iteratee(array[index], index, array) === false) {
    break;
  }
}
return array;

}

/**

* A specialized version of `_.includes` for arrays without support for
* specifying an index to search from.
*
* @private
* @param {Array} [array] The array to inspect.
* @param {*} target The value to search for.
* @returns {boolean} Returns `true` if `target` is found, else `false`.
*/

function arrayIncludes(array, value) {

var length = array ? array.length : 0;
return !!length && baseIndexOf(array, value, 0) > -1;

}

/**

* The base implementation of `_.findIndex` and `_.findLastIndex` without
* support for iteratee shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} predicate The function invoked per iteration.
* @param {number} fromIndex The index to search from.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched value, else `-1`.
*/

function baseFindIndex(array, predicate, fromIndex, fromRight) {

var length = array.length,
    index = fromIndex + (fromRight ? 1 : -1);

while ((fromRight ? index-- : ++index < length)) {
  if (predicate(array[index], index, array)) {
    return index;
  }
}
return -1;

}

/**

* The base implementation of `_.indexOf` without `fromIndex` bounds checks.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/

function baseIndexOf(array, value, fromIndex) {

if (value !== value) {
  return baseFindIndex(array, baseIsNaN, fromIndex);
}
var index = fromIndex - 1,
    length = array.length;

while (++index < length) {
  if (array[index] === value) {
    return index;
  }
}
return -1;

}

/**

* The base implementation of `_.isNaN` without support for number objects.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
*/

function baseIsNaN(value) {

return value !== value;

}

/**

* Gets the number of `placeholder` occurrences in `array`.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} placeholder The placeholder to search for.
* @returns {number} Returns the placeholder count.
*/

function countHolders(array, placeholder) {

var length = array.length,
    result = 0;

while (length--) {
  if (array[length] === placeholder) {
    result++;
  }
}
return result;

}

/**

* Gets the value at `key` of `object`.
*
* @private
* @param {Object} [object] The object to query.
* @param {string} key The key of the property to get.
* @returns {*} Returns the property value.
*/

function getValue(object, key) {

return object == null ? undefined : object[key];

}

/**

* Checks if `value` is a host object in IE < 9.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a host object, else `false`.
*/

function isHostObject(value) {

// Many host objects are `Object` objects that can coerce to strings
// despite having improperly defined `toString` methods.
var result = false;
if (value != null && typeof value.toString != 'function') {
  try {
    result = !!(value + '');
  } catch (e) {}
}
return result;

}

/**

* Replaces all `placeholder` elements in `array` with an internal placeholder
* and returns an array of their indexes.
*
* @private
* @param {Array} array The array to modify.
* @param {*} placeholder The placeholder to replace.
* @returns {Array} Returns the new array of placeholder indexes.
*/

function replaceHolders(array, placeholder) {

var index = -1,
    length = array.length,
    resIndex = 0,
    result = [];

while (++index < length) {
  var value = array[index];
  if (value === placeholder || value === PLACEHOLDER) {
    array[index] = PLACEHOLDER;
    result[resIndex++] = index;
  }
}
return result;

}

/** Used for built-in method references. */ var funcProto = Function.prototype,

objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */ var coreJsData = root[‘core-js_shared’];

/** Used to detect methods masquerading as native. */ var maskSrcKey = (function() {

var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
return uid ? ('Symbol(src)_1.' + uid) : '';

}());

/** Used to resolve the decompiled source of functions. */ var funcToString = funcProto.toString;

/** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty;

/**

* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/

var objectToString = objectProto.toString;

/** Used to detect if a method is native. */ var reIsNative = RegExp('^' +

funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'

);

/** Built-in value references. */ var objectCreate = Object.create;

/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max,

nativeMin = Math.min;

/* Used to set `toString` methods. */ var defineProperty = (function() {

var func = getNative(Object, 'defineProperty'),
    name = getNative.name;

return (name && name.length > 2) ? func : undefined;

}());

/**

* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} prototype The object to inherit from.
* @returns {Object} Returns the new object.
*/

function baseCreate(proto) {

return isObject(proto) ? objectCreate(proto) : {};

}

/**

* The base implementation of `_.isNative` without bad shim checks.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a native function,
*  else `false`.
*/

function baseIsNative(value) {

if (!isObject(value) || isMasked(value)) {
  return false;
}
var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
return pattern.test(toSource(value));

}

/**

* The base implementation of `_.rest` which doesn't validate or coerce arguments.
*
* @private
* @param {Function} func The function to apply a rest parameter to.
* @param {number} [start=func.length-1] The start position of the rest parameter.
* @returns {Function} Returns the new function.
*/

function baseRest(func, start) {

start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
return function() {
  var args = arguments,
      index = -1,
      length = nativeMax(args.length - start, 0),
      array = Array(length);

  while (++index < length) {
    array[index] = args[start + index];
  }
  index = -1;
  var otherArgs = Array(start + 1);
  while (++index < start) {
    otherArgs[index] = args[index];
  }
  otherArgs[start] = array;
  return apply(func, this, otherArgs);
};

}

/**

* Creates an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments.
*
* @private
* @param {Array} args The provided arguments.
* @param {Array} partials The arguments to prepend to those provided.
* @param {Array} holders The `partials` placeholder indexes.
* @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/

function composeArgs(args, partials, holders, isCurried) {

var argsIndex = -1,
    argsLength = args.length,
    holdersLength = holders.length,
    leftIndex = -1,
    leftLength = partials.length,
    rangeLength = nativeMax(argsLength - holdersLength, 0),
    result = Array(leftLength + rangeLength),
    isUncurried = !isCurried;

while (++leftIndex < leftLength) {
  result[leftIndex] = partials[leftIndex];
}
while (++argsIndex < holdersLength) {
  if (isUncurried || argsIndex < argsLength) {
    result[holders[argsIndex]] = args[argsIndex];
  }
}
while (rangeLength--) {
  result[leftIndex++] = args[argsIndex++];
}
return result;

}

/**

* This function is like `composeArgs` except that the arguments composition
* is tailored for `_.partialRight`.
*
* @private
* @param {Array} args The provided arguments.
* @param {Array} partials The arguments to append to those provided.
* @param {Array} holders The `partials` placeholder indexes.
* @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/

function composeArgsRight(args, partials, holders, isCurried) {

var argsIndex = -1,
    argsLength = args.length,
    holdersIndex = -1,
    holdersLength = holders.length,
    rightIndex = -1,
    rightLength = partials.length,
    rangeLength = nativeMax(argsLength - holdersLength, 0),
    result = Array(rangeLength + rightLength),
    isUncurried = !isCurried;

while (++argsIndex < rangeLength) {
  result[argsIndex] = args[argsIndex];
}
var offset = argsIndex;
while (++rightIndex < rightLength) {
  result[offset + rightIndex] = partials[rightIndex];
}
while (++holdersIndex < holdersLength) {
  if (isUncurried || argsIndex < argsLength) {
    result[offset + holders[holdersIndex]] = args[argsIndex++];
  }
}
return result;

}

/**

* Copies the values of `source` to `array`.
*
* @private
* @param {Array} source The array to copy values from.
* @param {Array} [array=[]] The array to copy values to.
* @returns {Array} Returns `array`.
*/

function copyArray(source, array) {

var index = -1,
    length = source.length;

array || (array = Array(length));
while (++index < length) {
  array[index] = source[index];
}
return array;

}

/**

* Creates a function that wraps `func` to invoke it with the optional `this`
* binding of `thisArg`.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} [thisArg] The `this` binding of `func`.
* @returns {Function} Returns the new wrapped function.
*/

function createBind(func, bitmask, thisArg) {

var isBind = bitmask & BIND_FLAG,
    Ctor = createCtor(func);

function wrapper() {
  var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  return fn.apply(isBind ? thisArg : this, arguments);
}
return wrapper;

}

/**

* Creates a function that produces an instance of `Ctor` regardless of
* whether it was invoked as part of a `new` expression or by `call` or `apply`.
*
* @private
* @param {Function} Ctor The constructor to wrap.
* @returns {Function} Returns the new wrapped function.
*/

function createCtor(Ctor) {

return function() {
  // Use a `switch` statement to work with class constructors. See
  // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
  // for more details.
  var args = arguments;
  switch (args.length) {
    case 0: return new Ctor;
    case 1: return new Ctor(args[0]);
    case 2: return new Ctor(args[0], args[1]);
    case 3: return new Ctor(args[0], args[1], args[2]);
    case 4: return new Ctor(args[0], args[1], args[2], args[3]);
    case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
    case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
    case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
  }
  var thisBinding = baseCreate(Ctor.prototype),
      result = Ctor.apply(thisBinding, args);

  // Mimic the constructor's `return` behavior.
  // See https://es5.github.io/#x13.2.2 for more details.
  return isObject(result) ? result : thisBinding;
};

}

/**

* Creates a function that wraps `func` to enable currying.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {number} arity The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/

function createCurry(func, bitmask, arity) {

var Ctor = createCtor(func);

function wrapper() {
  var length = arguments.length,
      args = Array(length),
      index = length,
      placeholder = getHolder(wrapper);

  while (index--) {
    args[index] = arguments[index];
  }
  var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
    ? []
    : replaceHolders(args, placeholder);

  length -= holders.length;
  if (length < arity) {
    return createRecurry(
      func, bitmask, createHybrid, wrapper.placeholder, undefined,
      args, holders, undefined, undefined, arity - length);
  }
  var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  return apply(fn, this, args);
}
return wrapper;

}

/**

* Creates a function that wraps `func` to invoke it with optional `this`
* binding of `thisArg`, partial application, and currying.
*
* @private
* @param {Function|string} func The function or method name to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to prepend to those provided to
*  the new function.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [partialsRight] The arguments to append to those provided
*  to the new function.
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/

function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {

var isAry = bitmask & ARY_FLAG,
    isBind = bitmask & BIND_FLAG,
    isBindKey = bitmask & BIND_KEY_FLAG,
    isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
    isFlip = bitmask & FLIP_FLAG,
    Ctor = isBindKey ? undefined : createCtor(func);

function wrapper() {
  var length = arguments.length,
      args = Array(length),
      index = length;

  while (index--) {
    args[index] = arguments[index];
  }
  if (isCurried) {
    var placeholder = getHolder(wrapper),
        holdersCount = countHolders(args, placeholder);
  }
  if (partials) {
    args = composeArgs(args, partials, holders, isCurried);
  }
  if (partialsRight) {
    args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
  }
  length -= holdersCount;
  if (isCurried && length < arity) {
    var newHolders = replaceHolders(args, placeholder);
    return createRecurry(
      func, bitmask, createHybrid, wrapper.placeholder, thisArg,
      args, newHolders, argPos, ary, arity - length
    );
  }
  var thisBinding = isBind ? thisArg : this,
      fn = isBindKey ? thisBinding[func] : func;

  length = args.length;
  if (argPos) {
    args = reorder(args, argPos);
  } else if (isFlip && length > 1) {
    args.reverse();
  }
  if (isAry && ary < length) {
    args.length = ary;
  }
  if (this && this !== root && this instanceof wrapper) {
    fn = Ctor || createCtor(fn);
  }
  return fn.apply(thisBinding, args);
}
return wrapper;

}

/**

* Creates a function that wraps `func` to invoke it with the `this` binding
* of `thisArg` and `partials` prepended to the arguments it receives.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} partials The arguments to prepend to those provided to
*  the new function.
* @returns {Function} Returns the new wrapped function.
*/

function createPartial(func, bitmask, thisArg, partials) {

var isBind = bitmask & BIND_FLAG,
    Ctor = createCtor(func);

function wrapper() {
  var argsIndex = -1,
      argsLength = arguments.length,
      leftIndex = -1,
      leftLength = partials.length,
      args = Array(leftLength + argsLength),
      fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;

  while (++leftIndex < leftLength) {
    args[leftIndex] = partials[leftIndex];
  }
  while (argsLength--) {
    args[leftIndex++] = arguments[++argsIndex];
  }
  return apply(fn, isBind ? thisArg : this, args);
}
return wrapper;

}

/**

* Creates a function that wraps `func` to continue currying.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {Function} wrapFunc The function to create the `func` wrapper.
* @param {*} placeholder The placeholder value.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to prepend to those provided to
*  the new function.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/

function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {

var isCurry = bitmask & CURRY_FLAG,
    newHolders = isCurry ? holders : undefined,
    newHoldersRight = isCurry ? undefined : holders,
    newPartials = isCurry ? partials : undefined,
    newPartialsRight = isCurry ? undefined : partials;

bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);

if (!(bitmask & CURRY_BOUND_FLAG)) {
  bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
}

var result = wrapFunc(func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity);
result.placeholder = placeholder;
return setWrapToString(result, func, bitmask);

}

/**

* Creates a function that either curries or invokes `func` with optional
* `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to wrap.
* @param {number} bitmask The bitmask flags.
*  The bitmask may be composed of the following flags:
*     1 - `_.bind`
*     2 - `_.bindKey`
*     4 - `_.curry` or `_.curryRight` of a bound function
*     8 - `_.curry`
*    16 - `_.curryRight`
*    32 - `_.partial`
*    64 - `_.partialRight`
*   128 - `_.rearg`
*   256 - `_.ary`
*   512 - `_.flip`
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to be partially applied.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/

function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {

var isBindKey = bitmask & BIND_KEY_FLAG;
if (!isBindKey && typeof func != 'function') {
  throw new TypeError(FUNC_ERROR_TEXT);
}
var length = partials ? partials.length : 0;
if (!length) {
  bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
  partials = holders = undefined;
}
ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
arity = arity === undefined ? arity : toInteger(arity);
length -= holders ? holders.length : 0;

if (bitmask & PARTIAL_RIGHT_FLAG) {
  var partialsRight = partials,
      holdersRight = holders;

  partials = holders = undefined;
}

var newData = [
  func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
  argPos, ary, arity
];

func = newData[0];
bitmask = newData[1];
thisArg = newData[2];
partials = newData[3];
holders = newData[4];
arity = newData[9] = newData[9] == null
  ? (isBindKey ? 0 : func.length)
  : nativeMax(newData[9] - length, 0);

if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) {
  bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG);
}
if (!bitmask || bitmask == BIND_FLAG) {
  var result = createBind(func, bitmask, thisArg);
} else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
  result = createCurry(func, bitmask, arity);
} else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
  result = createPartial(func, bitmask, thisArg, partials);
} else {
  result = createHybrid.apply(undefined, newData);
}
return setWrapToString(result, func, bitmask);

}

/**

* Gets the argument placeholder value for `func`.
*
* @private
* @param {Function} func The function to inspect.
* @returns {*} Returns the placeholder value.
*/

function getHolder(func) {

var object = func;
return object.placeholder;

}

/**

* Gets the native function at `key` of `object`.
*
* @private
* @param {Object} object The object to query.
* @param {string} key The key of the method to get.
* @returns {*} Returns the function if it's native, else `undefined`.
*/

function getNative(object, key) {

var value = getValue(object, key);
return baseIsNative(value) ? value : undefined;

}

/**

* Extracts wrapper details from the `source` body comment.
*
* @private
* @param {string} source The source to inspect.
* @returns {Array} Returns the wrapper details.
*/

function getWrapDetails(source) {

var match = source.match(reWrapDetails);
return match ? match[1].split(reSplitDetails) : [];

}

/**

* Inserts wrapper `details` in a comment at the top of the `source` body.
*
* @private
* @param {string} source The source to modify.
* @returns {Array} details The details to insert.
* @returns {string} Returns the modified source.
*/

function insertWrapDetails(source, details) {

var length = details.length,
    lastIndex = length - 1;

details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
details = details.join(length > 2 ? ', ' : ' ');
return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');

}

/**

* Checks if `value` is a valid array-like index.
*
* @private
* @param {*} value The value to check.
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
*/

function isIndex(value, length) {

length = length == null ? MAX_SAFE_INTEGER : length;
return !!length &&
  (typeof value == 'number' || reIsUint.test(value)) &&
  (value > -1 && value % 1 == 0 && value < length);

}

/**

* Checks if `func` has its source masked.
*
* @private
* @param {Function} func The function to check.
* @returns {boolean} Returns `true` if `func` is masked, else `false`.
*/

function isMasked(func) {

return !!maskSrcKey && (maskSrcKey in func);

}

/**

* Reorder `array` according to the specified indexes where the element at
* the first index is assigned as the first element, the element at
* the second index is assigned as the second element, and so on.
*
* @private
* @param {Array} array The array to reorder.
* @param {Array} indexes The arranged array indexes.
* @returns {Array} Returns `array`.
*/

function reorder(array, indexes) {

var arrLength = array.length,
    length = nativeMin(indexes.length, arrLength),
    oldArray = copyArray(array);

while (length--) {
  var index = indexes[length];
  array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
}
return array;

}

/**

* Sets the `toString` method of `wrapper` to mimic the source of `reference`
* with wrapper details in a comment at the top of the source body.
*
* @private
* @param {Function} wrapper The function to modify.
* @param {Function} reference The reference function.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @returns {Function} Returns `wrapper`.
*/

var setWrapToString = !defineProperty ? identity : function(wrapper, reference, bitmask) {

var source = (reference + '');
return defineProperty(wrapper, 'toString', {
  'configurable': true,
  'enumerable': false,
  'value': constant(insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)))
});

};

/**

* Converts `func` to its source code.
*
* @private
* @param {Function} func The function to process.
* @returns {string} Returns the source code.
*/

function toSource(func) {

if (func != null) {
  try {
    return funcToString.call(func);
  } catch (e) {}
  try {
    return (func + '');
  } catch (e) {}
}
return '';

}

/**

* Updates wrapper `details` based on `bitmask` flags.
*
* @private
* @returns {Array} details The details to modify.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @returns {Array} Returns `details`.
*/

function updateWrapDetails(details, bitmask) {

arrayEach(wrapFlags, function(pair) {
  var value = '_.' + pair[0];
  if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
    details.push(value);
  }
});
return details.sort();

}

/**

* Creates a function that invokes `func` with the `this` binding of `thisArg`
* and `partials` prepended to the arguments it receives.
*
* The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
* may be used as a placeholder for partially applied arguments.
*
* **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
* property of bound functions.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to bind.
* @param {*} thisArg The `this` binding of `func`.
* @param {...*} [partials] The arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* function greet(greeting, punctuation) {
*   return greeting + ' ' + this.user + punctuation;
* }
*
* var object = { 'user': 'fred' };
*
* var bound = _.bind(greet, object, 'hi');
* bound('!');
* // => 'hi fred!'
*
* // Bound with placeholders.
* var bound = _.bind(greet, object, _, '!');
* bound('hi');
* // => 'hi fred!'
*/

var bind = baseRest(function(func, thisArg, partials) {

var bitmask = BIND_FLAG;
if (partials.length) {
  var holders = replaceHolders(partials, getHolder(bind));
  bitmask |= PARTIAL_FLAG;
}
return createWrap(func, bitmask, thisArg, partials, holders);

});

/**

* Checks if `value` is classified as a `Function` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*
* _.isFunction(/abc/);
* // => false
*/

function isFunction(value) {

// The use of `Object#toString` avoids issues with the `typeof` operator
// in Safari 8-9 which returns 'object' for typed array and other constructors.
var tag = isObject(value) ? objectToString.call(value) : '';
return tag == funcTag || tag == genTag;

}

/**

* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/

function isObject(value) {

var type = typeof value;
return !!value && (type == 'object' || type == 'function');

}

/**

* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/

function isObjectLike(value) {

return !!value && typeof value == 'object';

}

/**

* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/

function isSymbol(value) {

return typeof value == 'symbol' ||
  (isObjectLike(value) && objectToString.call(value) == symbolTag);

}

/**

* Converts `value` to a finite number.
*
* @static
* @memberOf _
* @since 4.12.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted number.
* @example
*
* _.toFinite(3.2);
* // => 3.2
*
* _.toFinite(Number.MIN_VALUE);
* // => 5e-324
*
* _.toFinite(Infinity);
* // => 1.7976931348623157e+308
*
* _.toFinite('3.2');
* // => 3.2
*/

function toFinite(value) {

if (!value) {
  return value === 0 ? value : 0;
}
value = toNumber(value);
if (value === INFINITY || value === -INFINITY) {
  var sign = (value < 0 ? -1 : 1);
  return sign * MAX_INTEGER;
}
return value === value ? value : 0;

}

/**

* Converts `value` to an integer.
*
* **Note:** This method is loosely based on
* [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted integer.
* @example
*
* _.toInteger(3.2);
* // => 3
*
* _.toInteger(Number.MIN_VALUE);
* // => 0
*
* _.toInteger(Infinity);
* // => 1.7976931348623157e+308
*
* _.toInteger('3.2');
* // => 3
*/

function toInteger(value) {

var result = toFinite(value),
    remainder = result % 1;

return result === result ? (remainder ? result - remainder : result) : 0;

}

/**

* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/

function toNumber(value) {

if (typeof value == 'number') {
  return value;
}
if (isSymbol(value)) {
  return NAN;
}
if (isObject(value)) {
  var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
  value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
  return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
  ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
  : (reIsBadHex.test(value) ? NAN : +value);

}

/**

* Creates a function that returns `value`.
*
* @static
* @memberOf _
* @since 2.4.0
* @category Util
* @param {*} value The value to return from the new function.
* @returns {Function} Returns the new constant function.
* @example
*
* var objects = _.times(2, _.constant({ 'a': 1 }));
*
* console.log(objects);
* // => [{ 'a': 1 }, { 'a': 1 }]
*
* console.log(objects[0] === objects[1]);
* // => true
*/

function constant(value) {

return function() {
  return value;
};

}

/**

* This method returns the first argument it receives.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'a': 1 };
*
* console.log(_.identity(object) === object);
* // => true
*/

function identity(value) {

return value;

}

// Assign default placeholders. bind.placeholder = {};

module.exports = bind;