text: var unindent = require('../utils/unindent');
  
  var group = '';
  
  // Search: group, type, optional, fieldname, defaultValue, size, description
  // Example: {String{1..4}} [user.name='John Doe'] Users fullname.
  //
  // Naming convention:
  //     b -> begin
  //     e -> end
  //     name -> the field value
  //     oName -> wrapper for optional field
  //     wName -> wrapper for field
  var regExp = {
      b:               '^',                                   // start
      oGroup: {                                               // optional group: (404)
          b:               '\\s*(?:\\(\\s*',                  // starting with '(', optional surrounding spaces
          group:              '(.+?)',                        // 1
          e:               '\\s*\\)\\s*)?'                    // ending with ')', optional surrounding spaces
      },
      oType: {                                                // optional type: {string}
          b:               '\\s*(?:\\{\\s*',                  // starting with '{', optional surrounding spaces
          type:                '([a-zA-Z0-9\(\)#:\\.\\/\\\\\\[\\]_\|-]+)', // 2
          oSize: {                                            // optional size within type: {string{1..4}}
              b:               '\\s*(?:\\{\\s*',              // starting with '{', optional surrounding spaces
              size:                '(.+?)',                   // 3
              e:               '\\s*\\}\\s*)?'                // ending with '}', optional surrounding spaces
          },
          oAllowedValues: {                                   // optional allowed values within type: {string='abc','def'}
              b:               '\\s*(?:=\\s*',                // starting with '=', optional surrounding spaces
              possibleValues:      '(.+?)',                   // 4
              e:               '(?=\\s*\\}\\s*))?'            // ending with '}', optional surrounding spaces
          },
          e:               '\\s*\\}\\s*)?'                    // ending with '}', optional surrounding spaces
      },
      wName: {
          b:               '(\\[?\\s*',                       // 5 optional optional-marker
          name:                '([#@a-zA-Z0-9\\$\\:\\.\\/\\\\_-]+',   // 6
              withArray:           '(?:\\[[a-zA-Z0-9\\.\\/\\\\_-]*\\])?)', // https://github.com/apidoc/apidoc-core/pull/4
          oDefaultValue: {                                    // optional defaultValue
              b:               '(?:\\s*=\\s*(?:',             // starting with '=', optional surrounding spaces
              withDoubleQuote:     '"([^"]*)"',               // 7
              withQuote:           '|\'([^\']*)\'',           // 8
              withoutQuote:        '|(.*?)(?:\\s|\\]|$)',     // 9
              e:               '))?'
          },
          e:               '\\s*\\]?\\s*)'
      },
      description:         '(.*)?',                           // 10
      e:               '$|@'
  };
  
  function _objectValuesToString(obj) {
      var str = '';
      for (var el in obj) {
          if (typeof obj[el] === 'string')
              str += obj[el];
          else
              str += _objectValuesToString(obj[el]);
      }
      return str;
  }
  
  var parseRegExp = new RegExp(_objectValuesToString(regExp));
  
  var allowedValuesWithDoubleQuoteRegExp = new RegExp(/\"[^\"]*[^\"]\"/g);
  var allowedValuesWithQuoteRegExp = new RegExp(/\'[^\']*[^\']\'/g);
  var allowedValuesRegExp = new RegExp(/[^,\s]+/g);
  
  function parse(content, source, defaultGroup) {
      content = content.trim();
  
      // replace Linebreak with Unicode
      content = content.replace(/\n/g, '\uffff');
  
      var matches = parseRegExp.exec(content);
  
      if ( ! matches)
          return null;
  
      // reverse Unicode Linebreaks
      matches.forEach(function (val, index, array) {
          if (val) {
              array[index] = val.replace(/\uffff/g, '\n');
          }
      });
  
      var allowedValues = matches[4];
      if (allowedValues) {
          var regExp;
          if (allowedValues.charAt(0) === '"')
              regExp = allowedValuesWithDoubleQuoteRegExp;
          else if (allowedValues.charAt(0) === '\'')
              regExp = allowedValuesWithQuoteRegExp;
          else
              regExp = allowedValuesRegExp;
  
          var allowedValuesMatch;
          var list = [];
  
          while ( (allowedValuesMatch = regExp.exec(allowedValues)) ) {
              list.push(allowedValuesMatch[0]);
          }
          allowedValues = list;
      }
  
      // Set global group variable
      group = matches[1] || defaultGroup || 'Parameter';
  
      return {
          group        : group,
          type         : matches[2],
          size         : matches[3],
          allowedValues: allowedValues,
          optional     : (matches[5] && matches[5][0] === '[') ? true : false,
          field        : matches[6],
          defaultValue : matches[7] || matches[8] || matches[9],
          description  : unindent(matches[10] || '')
      };
  }
  
  function path() {
      return 'local.parameter.fields.' + getGroup();
  }
  
  function getGroup() {
      return group;
  }
  
  /**
   * Exports
   */
  module.exports = {
      parse         : parse,
      path          : path,
      method        : 'push',
      getGroup      : getGroup,
      markdownFields: [ 'description', 'type' ],
      markdownRemovePTags: [ 'type' ]
  };
  