public static Message parse(String in)
	{
		Message message = new Message();
		if (in.startsWith("@"))
		{
			String[] tags = in.substring(1)
				.split(";");
			for (String tag : tags)
			{
				int eq = tag.indexOf('=');
				if (eq == -1) continue;

				String key = tag.substring(0, eq);
				String value = tag.substring(eq + 1)
					.replace("\\:", ";")
					.replace("\\s", " ")
					.replace("\\\\", "\\")
					.replace("\\r", "\r")
					.replace("\\n", "\n");

				message.tags.put(key, value);
			}

			int sp = in.indexOf(' ');
			in = in.substring(sp + 1);
		}

		if (in.startsWith(":"))
		{
			int sp = in.indexOf(' ');
			message.source = in.substring(1, sp);

			in = in.substring(sp + 1);
		}

		int sp = in.indexOf(' ');
		if (sp == -1)
		{
			message.command = in;
			message.arguments = new String[0];
			return message;
		}

		message.command = in.substring(0, sp);

		String args = in.substring(sp + 1);
		List<String> argList = new ArrayList<>();
		do
		{
			String arg;
			if (args.startsWith(":"))
			{
				arg = args.substring(1);
				sp = -1;
			}
			else
			{
				sp = args.indexOf(' ');
				arg = sp == -1 ? args : args.substring(0, sp);
			}
			args = args.substring(sp + 1);
			argList.add(arg);
		} while (sp != -1);

		message.arguments = argList.toArray(new String[0]);
		return message;
	}
@Test
	public void testParse()
	{
		Message message = Message.parse("@badges=subscriber/0;color=;display-name=kappa_kid_;emotes=;id=6539b42a-e945-4a83-a5b7-018149ca9fa7;mod=0;room-id=27107346;subscriber=1;tmi-sent-ts=1535926830652;turbo=0;user-id=33390095;user-type= :kappa_kid_!kappa_kid_@kappa_kid_.tmi.twitch.tv PRIVMSG #b0aty :how do u add charges to that zeah book?");
		Map<String, String> messageTags = message.getTags();
		assertEquals("subscriber/0", messageTags.get("badges"));
		assertEquals("kappa_kid_!kappa_kid_@kappa_kid_.tmi.twitch.tv", message.getSource());
		assertEquals("PRIVMSG", message.getCommand());
		assertEquals("#b0aty", message.getArguments()[0]);
		assertEquals("how do u add charges to that zeah book?", message.getArguments()[1]);

		message = Message.parse("@badges=moderator/1,subscriber/12,bits/10000;color=#008000;display-name=Am_Sephiroth;emotes=;id=7d516b7c-de7a-4c8b-ad23-d8880b55d46b;login=am_sephiroth;mod=1;msg-id=subgift;msg-param-months=8;msg-param-recipient-display-name=IntRS;msg-param-recipient-id=189672346;msg-param-recipient-user-name=intrs;msg-param-sender-count=215;msg-param-sub-plan-name=Sick\\sNerd\\sSubscription\\s;msg-param-sub-plan=1000;room-id=49408183;subscriber=1;system-msg=Am_Sephiroth\\sgifted\\sa\\sTier\\s1\\ssub\\sto\\sIntRS!\\sThey\\shave\\sgiven\\s215\\sGift\\sSubs\\sin\\sthe\\schannel!;tmi-sent-ts=1535980032939;turbo=0;user-id=69539403;user-type=mod :tmi.twitch.tv USERNOTICE #sick_nerd");
		messageTags = message.getTags();
		assertEquals("Am_Sephiroth gifted a Tier 1 sub to IntRS! They have given 215 Gift Subs in the channel!", messageTags.get("system-msg"));
	}