const ANONYMOUS = '<<anonymous>>';

// Pulled from: https://github.com/facebook/react/blob/master/src/isomorphic/classic/types/ReactPropTypes.js#L108
function createChainableTypeChecker(validate) {
  function checkType(
    isRequired,
    props,
    propName,
    componentName = ANONYMOUS
  ) {
    if (props[propName] == null) {
      if (isRequired) {
        if (props[propName] === null) {
          return new Error(
            `The \`${propName}\` is marked as required ` +
            `in \`${componentName}\`, but its value is \`null\`.`
          );
        }

        return new Error(
          `The \`${propName}\` is marked as required in ` +
          `\`${componentName}\`, but its value is \`undefined\`.`
        );
      }

      return null;
    }

    return validate(
      props,
      propName,
      componentName
    );
  }

  // Use of .bind for creating the chainable `.isRequired` interface
  const chainedCheckType = checkType.bind(null, false);
  chainedCheckType.isRequired = checkType.bind(null, true);

  return chainedCheckType;
}

function createCustomTypeChecker(
  callback,
  message
) {
  // See customProp: https://facebook.github.io/react/docs/reusable-components.html#prop-validation
  // Ideally, propTypes should be validated only in development:
  // https://facebook.github.io/react/warnings/dont-call-proptypes.html
  return function validate(
    props,
    propName,
    componentName
  ) {
    const prop = props[propName];

    if (typeof callback(prop) !== 'boolean') {
      return new Error(
        'ERROR MESSAGE for the callback to evaluate to a boolean value'
      );
    }
    if (!!message && typeof message !== 'string') {
      return new Error(
        'ERROR MESSAGE for the string param to be of type string'
      );
    }

    /* eslint-disable no-param-reassign */
    message = message || 'DEFAULT MESSAGE';
    /* eslint-enable no-param-reassign */

    if (!callback(prop)) {
      return new Error(message);
    }

    return null;
  };
}

function createPropType(callback, message) {
  return createChainableTypeChecker(
    createCustomTypeChecker(callback, message)
  );
}

export default createPropType;

@@ -1555,226 +1555,447 @@
    '
-ERROR MESSAGE for the callback to evaluate to a boolean value'%0A      );%0A    %7D%0A    if (!!message && typeof message !== 'string') %7B%0A      return new Error(%0A        'ERROR MESSAGE for the string param to be of type string
+Invalid createPropType input: callback parameter must evaluate to a boolean value.' +%0A        'See https://github.com/jackrzhang/react-create-proptype#parameters for details.'%0A      );%0A    %7D%0A    if (!!message && typeof message !== 'string') %7B%0A      return new Error(%0A        'Invalid createPropType input: message parameter must be of type string.' +%0A        'See https://github.com/jackrzhang/react-create-proptype#parameters for details.
 '%0A  
@@ -2043,24 +2043,33 @@
 ram-reassign
+, max-len
  */%0A    mess
@@ -2089,25 +2089,91 @@
  %7C%7C 
-'DEFAULT MESSAGE'
+%60Invalid prop %5C%60$%7BpropName%7D%5C%60 supplied to %5C%60$%7BcomponentName%7D%5C%60. Validation failed.%60
 ;%0A  
@@ -2208,16 +2208,25 @@
 reassign
+, max-len
  */%0A%0A   

Create error messages for createPropType's custom validator creator