const PROTO_VER_1_10 = require('minecraft-data')('1.10.2').version.version

module.exports = inject

function inject (bot, options) {
  const CHAT_LENGTH_LIMIT = options.chatLengthLimit || ((bot.protocolVersion > PROTO_VER_1_10) ? 256 : 100)

  const ChatMessage = require('../chat_message')(bot.version)
  // add an array, containing objects such as {pattern:/regex pattern/, chatType:"string", description:"string"}
  // chat.pattern.type will emit an event for bot.on() of the same type, eg chatType = whisper will trigger bot.on('whisper')
  // Default patterns for matching vanilla chat.
  bot.chatPatterns = [
    {
      pattern: /^<(?:.+? )?(.+?)> (.*)$/,
      type: 'chat',
      description: 'Vanilla chat'
    },
    {
      pattern: /^(?:.+? )?(.+?) (?:whispers to you:|whispers) (.*)$/,
      type: 'whisper',
      description: 'Vanilla whisper'
    }
  ]

  bot.chatAddPattern = (patternValue, typeValue, descriptionValue) => {
    // description is not required but recommended
    if (typeof descriptionValue === 'undefined') {
      descriptionValue = 'None'
    }
    bot.chatPatterns.push({
      pattern: patternValue,
      type: typeValue,
      description: descriptionValue
    })
  }

  bot._client.on('chat', (packet) => {
    function checkForChatPatterns (msg) {
      const stringMsg = msg.toString()
      // iterate through each object in chat.patterns array and test if .pattern matches
      for (let i = 0; i < bot.chatPatterns.length; i++) {
        const match = stringMsg.match(bot.chatPatterns[i].pattern)
        if (match) {
          bot.emit(bot.chatPatterns[i].type, ...match.slice(1), msg.translate, msg)
        }
      }
    }

    var msg
    try {
      msg = new ChatMessage(JSON.parse(packet.message))
    } catch (e) {
      msg = new ChatMessage(packet.message)
    }
    bot.emit('message', msg)
    checkForChatPatterns(msg)

    // Position 2 is the action bar
    if (packet.position === 2) bot.emit('actionBar', msg)
  })

  function chatWithHeader (header, message) {
    const lengthLimit = CHAT_LENGTH_LIMIT - header.length
    message.split('\n').forEach((subMessage) => {
      if (!subMessage) return
      let i
      let smallMsg
      for (i = 0; i < subMessage.length; i += lengthLimit) {
        smallMsg = header + subMessage.substring(i, i + lengthLimit)
        bot._client.write('chat', { message: smallMsg })
      }
    })
  }

  function tabComplete (text, cb, assumeCommand = false, sendBlockInSight = true) {
    let position

    if (sendBlockInSight) {
      const block = bot.blockInSight()

      if (block) {
        position = block.position
      }
    }

    bot._client.once('tab_complete', (packet) => {
      cb(undefined, packet.matches)
    })

    bot._client.write('tab_complete', {
      text,
      assumeCommand,
      lookedAtBlock: position
    })
  }

  bot.whisper = (username, message) => {
    chatWithHeader(`/tell ${username} `, message)
  }
  bot.chat = (message) => {
    chatWithHeader('', message)
  }

  bot.tabComplete = tabComplete
}

@@ -234,16 +234,75 @@
 6 : 100)
+%0A  const USERNAME_REGEX = '(?:%5C%5C(.+%5C%5C)%7C%5C%5C%5B.+%5C%5C%5D%7C.)*?(%5C%5Cw+)'
 %0A%0A  cons
@@ -602,124 +602,111 @@
 )%0A  
-// Default patterns for matching vanilla chat.%0A  bot.chatPatterns = %5B%0A    %7B%0A      pattern: /%5E%3C(?:.+? )?(.+?)%3E
+bot.chatPatterns = %5B%0A    %7B%0A      pattern: new RegExp(%60%5E$%7BUSERNAME_REGEX%7D whispers(?: to you)?:?
  (.*)$
-/
+%60)
 ,%0A  
@@ -716,20 +716,23 @@
  type: '
-chat
+whisper
 ',%0A     
@@ -754,20 +754,23 @@
 Vanilla 
-chat
+whisper
 '%0A    %7D,
@@ -795,61 +795,217 @@
 rn: 
-/%5E(?:.+? )?(.+?) (?:whispers to you:%7Cwhispers) 
+new RegExp(%60%5E%5C%5C%5B$%7BUSERNAME_REGEX%7D -%3E %5C%5Cw+%5C%5Cs?%5C%5C%5D (.*)$%60),%0A      type: 'whisper',%0A      description: 'Essentials whisper'%0A    %7D,%0A    %7B%0A      pattern: new RegExp(%60%5E$%7BUSERNAME_REGEX%7D%5C%5Cs?%5B%3E:%5C%5C-%C2%BB%5C%5C%5D%5C%5C)~%5D+%5C%5Cs
 (.*)$
-/
+%60)
 ,%0A  
@@ -1007,39 +1007,36 @@
 ),%0A      type: '
-whisper
+chat
 ',%0A      descrip
@@ -1038,39 +1038,38 @@
 scription: '
-Vanilla whisper
+Universal chat
 '%0A    %7D%0A  %5D%0A
@@ -1529,16 +1529,43 @@
 tring()%0A
+      let matchAny = false%0A
       //
@@ -1660,54 +1660,168 @@
 or (
-let i = 0; i %3C bot.chatPatterns.length; i++) %7B
+const %7B pattern, type %7D of bot.chatPatterns) %7B%0A        // Chat pattern matches server messages so drop them%0A        if (stringMsg.startsWith('%5BServer:')) break%0A
 %0A   
@@ -1855,36 +1855,16 @@
 g.match(
-bot.chatPatterns%5Bi%5D.
 pattern)
@@ -1899,37 +1899,43 @@
     
-bot.emit(bot.chatPatterns%5Bi%5D.
+matchAny = true%0A          bot.emit(
 type
@@ -1984,32 +1984,125 @@
        %7D%0A      %7D
+%0A%0A      if (matchAny === false) %7B%0A        bot.emit('unmachedMessage', stringMsg, msg)%0A      %7D
 %0A    %7D%0A%0A    var 

Add universal chat pattern (#812)