@Subscribe
	public void onChatMessage(ChatMessage event)
	{
		if (event.getType() == ChatMessageType.GAMEMESSAGE || event.getType() == ChatMessageType.SPAM)
		{
			String message = Text.removeTags(event.getMessage());
			Matcher dodgyCheckMatcher = DODGY_CHECK_PATTERN.matcher(message);
			Matcher dodgyProtectMatcher = DODGY_PROTECT_PATTERN.matcher(message);
			Matcher dodgyBreakMatcher = DODGY_BREAK_PATTERN.matcher(message);
			Matcher bindingNecklaceCheckMatcher = BINDING_CHECK_PATTERN.matcher(message);
			Matcher bindingNecklaceUsedMatcher = BINDING_USED_PATTERN.matcher(message);
			Matcher ringOfForgingCheckMatcher = RING_OF_FORGING_CHECK_PATTERN.matcher(message);
			Matcher amuletOfChemistryCheckMatcher = AMULET_OF_CHEMISTRY_CHECK_PATTERN.matcher(message);
			Matcher amuletOfChemistryUsedMatcher = AMULET_OF_CHEMISTRY_USED_PATTERN.matcher(message);
			Matcher amuletOfChemistryBreakMatcher = AMULET_OF_CHEMISTRY_BREAK_PATTERN.matcher(message);
			Matcher amuletOfBountyCheckMatcher = AMULET_OF_BOUNTY_CHECK_PATTERN.matcher(message);
			Matcher amuletOfBountyUsedMatcher = AMULET_OF_BOUNTY_USED_PATTERN.matcher(message);
			Matcher chronicleAddMatcher = CHRONICLE_ADD_PATTERN.matcher(message);
			Matcher chronicleUseAndCheckMatcher = CHRONICLE_USE_AND_CHECK_PATTERN.matcher(message);
			Matcher slaughterActivateMatcher = BRACELET_OF_SLAUGHTER_ACTIVATE_PATTERN.matcher(message);
			Matcher slaughterCheckMatcher = BRACELET_OF_SLAUGHTER_CHECK_PATTERN.matcher(message);
			Matcher expeditiousActivateMatcher = EXPEDITIOUS_BRACELET_ACTIVATE_PATTERN.matcher(message);
			Matcher expeditiousCheckMatcher = EXPEDITIOUS_BRACELET_CHECK_PATTERN.matcher(message);
			Matcher bloodEssenceCheckMatcher = BLOOD_ESSENCE_CHECK_PATTERN.matcher(message);
			Matcher bloodEssenceExtractMatcher = BLOOD_ESSENCE_EXTRACT_PATTERN.matcher(message);
			Matcher braceletOfClayCheckMatcher = BRACELET_OF_CLAY_CHECK_PATTERN.matcher(message);

			if (message.contains(RING_OF_RECOIL_BREAK_MESSAGE))
			{
				notifier.notify(config.recoilNotification(), "Your Ring of Recoil has shattered");
			}
			else if (dodgyBreakMatcher.find())
			{
				notifier.notify(config.dodgyNotification(), "Your dodgy necklace has crumbled to dust.");

				updateDodgyNecklaceCharges(MAX_DODGY_CHARGES);
			}
			else if (dodgyCheckMatcher.find())
			{
				updateDodgyNecklaceCharges(Integer.parseInt(dodgyCheckMatcher.group(1)));
			}
			else if (dodgyProtectMatcher.find())
			{
				updateDodgyNecklaceCharges(Integer.parseInt(dodgyProtectMatcher.group(1)));
			}
			else if (amuletOfChemistryCheckMatcher.find())
			{
				updateAmuletOfChemistryCharges(Integer.parseInt(amuletOfChemistryCheckMatcher.group(1)));
			}
			else if (amuletOfChemistryUsedMatcher.find())
			{
				final String match = amuletOfChemistryUsedMatcher.group(1);

				int charges = 1;
				if (!match.equals("one"))
				{
					charges = Integer.parseInt(match);
				}

				updateAmuletOfChemistryCharges(charges);
			}
			else if (amuletOfChemistryBreakMatcher.find())
			{
				notifier.notify(config.amuletOfChemistryNotification(), "Your amulet of chemistry has crumbled to dust.");

				updateAmuletOfChemistryCharges(MAX_AMULET_OF_CHEMISTRY_CHARGES);
			}
			else if (amuletOfBountyCheckMatcher.find())
			{
				updateAmuletOfBountyCharges(Integer.parseInt(amuletOfBountyCheckMatcher.group(1)));
			}
			else if (amuletOfBountyUsedMatcher.find())
			{
				updateAmuletOfBountyCharges(Integer.parseInt(amuletOfBountyUsedMatcher.group(1)));
			}
			else if (message.equals(AMULET_OF_BOUNTY_BREAK_TEXT))
			{
				updateAmuletOfBountyCharges(MAX_AMULET_OF_BOUNTY_CHARGES);
			}
			else if (message.contains(BINDING_BREAK_TEXT))
			{
				notifier.notify(config.bindingNotification(), BINDING_BREAK_TEXT);

				// This chat message triggers before the used message so add 1 to the max charges to ensure proper sync
				updateBindingNecklaceCharges(MAX_BINDING_CHARGES + 1);
			}
			else if (bindingNecklaceUsedMatcher.find())
			{
				final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
				if (equipment.contains(ItemID.BINDING_NECKLACE))
				{
					updateBindingNecklaceCharges(getItemCharges(ItemChargeConfig.KEY_BINDING_NECKLACE) - 1);
				}
			}
			else if (bindingNecklaceCheckMatcher.find())
			{
				final String match = bindingNecklaceCheckMatcher.group(1);

				int charges = 1;
				if (!match.equals("one"))
				{
					charges = Integer.parseInt(match);
				}

				updateBindingNecklaceCharges(charges);
			}
			else if (ringOfForgingCheckMatcher.find())
			{
				final String match = ringOfForgingCheckMatcher.group(1);

				int charges = 1;
				if (!match.equals("one"))
				{
					charges = Integer.parseInt(match);
				}
				updateRingOfForgingCharges(charges);
			}
			else if (message.equals(RING_OF_FORGING_USED_TEXT) || message.equals(RING_OF_FORGING_VARROCK_PLATEBODY))
			{
				final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
				final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);

				// Determine if the player smelted with a Ring of Forging equipped.
				if (equipment == null)
				{
					return;
				}

				if (equipment.contains(ItemID.RING_OF_FORGING) && (message.equals(RING_OF_FORGING_USED_TEXT) || inventory.count(ItemID.IRON_ORE) > 1))
				{
					int charges = Ints.constrainToRange(getItemCharges(ItemChargeConfig.KEY_RING_OF_FORGING) - 1, 0, MAX_RING_OF_FORGING_CHARGES);
					updateRingOfForgingCharges(charges);
				}
			}
			else if (message.equals(RING_OF_FORGING_BREAK_TEXT))
			{
				notifier.notify(config.ringOfForgingNotification(), "Your ring of forging has melted.");

				// This chat message triggers before the used message so add 1 to the max charges to ensure proper sync
				updateRingOfForgingCharges(MAX_RING_OF_FORGING_CHARGES + 1);
			}
			else if (chronicleAddMatcher.find())
			{
				final String match = chronicleAddMatcher.group(1);

				if (match.equals("one"))
				{
					setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1);
				}
				else
				{
					setItemCharges(ItemChargeConfig.KEY_CHRONICLE, Integer.parseInt(match));
				}
			}
			else if (chronicleUseAndCheckMatcher.find())
			{
				setItemCharges(ItemChargeConfig.KEY_CHRONICLE, Integer.parseInt(chronicleUseAndCheckMatcher.group(1)));
			}
			else if (message.equals(CHRONICLE_ONE_CHARGE_TEXT))
			{
				setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1);
			}
			else if (message.equals(CHRONICLE_EMPTY_TEXT) || message.equals(CHRONICLE_NO_CHARGES_TEXT))
			{
				setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 0);
			}
			else if (message.equals(CHRONICLE_FULL_TEXT))
			{
				setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1000);
			}
			else if (slaughterActivateMatcher.find())
			{
				final String found = slaughterActivateMatcher.group(1);
				if (found == null)
				{
					updateBraceletOfSlaughterCharges(MAX_SLAYER_BRACELET_CHARGES);
					notifier.notify(config.slaughterNotification(), BRACELET_OF_SLAUGHTER_BREAK_TEXT);
				}
				else
				{
					updateBraceletOfSlaughterCharges(Integer.parseInt(found));
				}
			}
			else if (slaughterCheckMatcher.find())
			{
				updateBraceletOfSlaughterCharges(Integer.parseInt(slaughterCheckMatcher.group(1)));
			}
			else if (expeditiousActivateMatcher.find())
			{
				final String found = expeditiousActivateMatcher.group(1);
				if (found == null)
				{
					updateExpeditiousBraceletCharges(MAX_SLAYER_BRACELET_CHARGES);
					notifier.notify(config.expeditiousNotification(), EXPEDITIOUS_BRACELET_BREAK_TEXT);
				}
				else
				{
					updateExpeditiousBraceletCharges(Integer.parseInt(found));
				}
			}
			else if (expeditiousCheckMatcher.find())
			{
				updateExpeditiousBraceletCharges(Integer.parseInt(expeditiousCheckMatcher.group(1)));
			}
			else if (bloodEssenceCheckMatcher.find())
			{
				updateBloodEssenceCharges(Integer.parseInt(bloodEssenceCheckMatcher.group(1)));
			}
			else if (bloodEssenceExtractMatcher.find())
			{
				updateBloodEssenceCharges(getItemCharges(ItemChargeConfig.KEY_BLOOD_ESSENCE) - Integer.parseInt(bloodEssenceExtractMatcher.group(1)));
			}
			else if (message.contains(BLOOD_ESSENCE_ACTIVATE_TEXT))
			{
				updateBloodEssenceCharges(MAX_BLOOD_ESSENCE_CHARGES);
			}
			else if (braceletOfClayCheckMatcher.find())
			{
				updateBraceletOfClayCharges(Integer.parseInt(braceletOfClayCheckMatcher.group(1)));
			}
			else if (message.equals(BRACELET_OF_CLAY_USE_TEXT) || message.equals(BRACELET_OF_CLAY_USE_TEXT_TRAHAEARN))
			{
				final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);

				// Determine if the player mined with a Bracelet of Clay equipped.
				if (equipment != null && equipment.contains(ItemID.BRACELET_OF_CLAY))
				{
					final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);

					// Charge is not used if only 1 inventory slot is available when mining in Prifddinas
					boolean ignore = inventory != null
						&& inventory.count() == 27
						&& message.equals(BRACELET_OF_CLAY_USE_TEXT_TRAHAEARN);

					if (!ignore)
					{
						int charges = Ints.constrainToRange(getItemCharges(ItemChargeConfig.KEY_BRACELET_OF_CLAY) - 1, 0, MAX_BRACELET_OF_CLAY_CHARGES);
						updateBraceletOfClayCharges(charges);
					}
				}
			}
			else if (message.equals(BRACELET_OF_CLAY_BREAK_TEXT))
			{
				notifier.notify(config.braceletOfClayNotification(), "Your bracelet of clay has crumbled to dust");
				updateBraceletOfClayCharges(MAX_BRACELET_OF_CLAY_CHARGES);
			}
		}
	}
@Test
	public void testChronicleAddSingleChargeFull()
	{
		ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_ADD_SINGLE_CHARGE_FULL, "", 0);
		itemChargePlugin.onChatMessage(chatMessage);
		verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1000);
	}