public interface TwirkListener {

	/**Fires for ever incoming message <b>except PING</b>.
	 *
	 * @param unformatedMessage The incoming message exactly as it looks from Twitch
	 */
    default public void onAnything( String unformatedMessage ) {}

	/**Fires for incoming PRIVMSG to the channel the bot is joined in
	 *
	 * @param sender The user who sent the message. Parsed from the incoming message's tag
	 * @param message The message that was sent, with the tag removed
	 */
    default public void onPrivMsg( TwitchUser  sender, TwitchMessage  message ) {}

	/**Fires for incoming WHISPER to the bot. Please note that a whisper does
         * not target a channel, and does not come from a channel. Thus, the flags
         * for whether a users is a subscriber or not cannot be looked at, since
         * the message didn't come through a channel chat room. Also, the 
         * {@link TwitchMessage#getTarget()} will always return the bot's name, since
         * the target of the whisper was the bot.
	 *
	 * @param sender The user who sent the message. Parsed from the incoming message's tag
	 * @param message The message that was sent, with the tag removed
	 */
	default public void onWhisper( TwitchUser  sender, TwitchMessage  message ) {}

	/**Fires when the bot receives a JOIN from Twitch. Note that Twitch sometimes drops
	 * PART messages, so we might receive a JOIN from a user who we never saw PART. Another
	 * important thing to note is that for large channels (1k chatters +), Twitch only sends
	 * JOINS/PARTS for moderators.<br><br>
	 *
	 * Also worth noting is that we don't see any properties for the joining user, we only see his/her
	 * Twitch user name in lower case
	 *
	 * @param joinedNick The joining users Twitch user name, in lower case
	 */
    default public void onJoin( String joinedNick ) {}

	/**Fires when the bot receives a PART from Twitch. Note that Twitch sometimes drops
	 * JOIN messages, so we might receive a PART from a user who we never saw JOIN. Another
	 * important thing to note is that for large channels (1k chatters +), Twitch only sends
	 * JOINS/PARTS for moderators.<br><br>
	 *
	 * Also worth noting is that we don't see any properties for the parting user, we only see his/her
	 * Twitch user name in lower case
	 *
	 * @param partedNick The parting users Twitch user name, in lower case
	 */
    default public void onPart( String partedNick ) {}

	/**Fires when we've successfully connected to Twitch's server and joined the channel
	 */
	default public void onConnect() {}

	/**Fires when we've received a request from Twitch, which asks us to reconnect to them
	 */
	default public void onReconnect() {}

	/**Fires when we've disconnected from Twitch's server. <br>
	 * We can try to reconnect onDisconnect
	 */
    default public void onDisconnect() {}

	/**Fires whenever we receive a NOTICE from Twitch. See {@link Notice }<br>
	 * NOTICE tells us about certain events, such as being Timed Out,
	 *
	 * @param notice The notice we received.
	 */
    default public void onNotice( Notice  notice ) {}

	/**Fires whenever we receive a HOSTTARGET from Twitch. See {@link HostTarget }
	 *
	 * @param hostNotice The host notice we received.
	 */
    default public void onHost( HostTarget  hostNotice ) {}

	/**
     * Fires whenever we receive a MODE from Twitch. See {@link Mode}.<br>
	 * A mode means that a user gained or lost moderator status. However, this
	 * is unreliable, and you should consider looking at the {@link TwitchUser } you
	 * receive in the {@link #onPrivMsg(TwitchUser , TwitchMessage )} instead. Twitch sends
	 * mode notices every now and then, and does not reliably reflect a users current status
	 *
	 * @param mode The mode notice
     * @deprecated Use the {@link TwitchUser#isMod()} method to track moderator status instead
	 */
    default public void onMode( Mode  mode ) {};

	/**Fires whenever we receive a USERSTATE from Twitch. See {@link Userstate }<br>
	 * USERSTATE is sent whenever the bot sends a message to Twirk. You should <b>never</b> respond
	 * to a USERSTATE, as that will create a cycle that will get your bot banned for spamming Twitch's
	 * server
	 *
	 * @param userstate The user state we received
	 */
    default public void onUserstate( Userstate  userstate ) {}

	/**Fires whenever we receive a ROOMSTATE from Twitch. See {@link Roomstate }<br>
	 * ROOMSTATE is sent when joining a channel and every time one of the chat room settings,
	 * like slow mode, change. <br>
	 * The message on join contains all room settings. <br>
	 * Changes only contain the relevant tag.
	 *
	 * @param roomstate The room state we received
	 */
    default public void onRoomstate( Roomstate  roomstate ) {}

	/**Fires when we receive a CLEARCHAT from Twitch. See {@link ClearChat }<br>
	 * CLEARCHAT comes in two modes: <ul>
	 * <li>USER - This clears everything a certain user has written in chat
	 * <li>TOTAL - This clear everything in chat
	 * </ul>
	 *
	 * @param clearChat The clear chat notice we received
	 */
    default public void onClearChat( ClearChat  clearChat ) {}

	/**Fires when we receive a CLEARMSG from Twitch. See {@link ClearMsg }<br>
	 * 
	 *
	 * @param clearMsg The clear msg notice we received
	 */
    default public void onClearMsg( ClearMsg  clearMsg ) {}

	/**Fires when we've successfully joined a channel and retrieved the list of
	 * all users that were online. <br><br>
	 * The <code>Collection</code> that is passed with this method contains
	 * the names of all the users that we received by the channels names-list. All these names are in lower case.<br>
	 * Note that this list is read-only. Trying to make changes to it will result in a <code>UnsupportedOperationException</code><br><br>
	 * Future changes to whom are online will be noticed via {@link #onJoin(String)} and {@link #onPart(String)} events
	 *
	 * @param namesList The unmodifiable collection of all users that Twitch told us were online in this channel.
	 */
    default public void onNamesList( Collection<String> namesList ) {}

	/**Fires when we receive a USERNOTICE from Twitch. See {@link Usernotice }<br>
	 * A Usernotice tells us about a re-subscription event, either to our channel or to the channel
	 * we are hosting.
	 *
     * @param user The TwitchUser that fired the Usernotice
	 * @param usernotice The Usernotice we received
	 */
    default public void onUsernotice(TwitchUser user, Usernotice usernotice) {}


	/**Fires when we received a message we could not categorize. This might happen
	 * if Twitch changes something suddenly, so we cannot parse the incomming message.
	 *
	 * @param unformatedMessage The incoming message exactly as it looks from Twitch
	 */
    default public void onUnknown( String unformatedMessage ) {}
} public interface ClearChat extends AbstractType{
	/** Retrieves the MODE of the CLEARCHAT. Can be USER, if a user was purged, or COMPLETE, if the entire chat was purged
	 *
	 * @return {@link CLEARCHAT_MODE} of this CLEARCHAT
	 */
	CLEARCHAT_MODE getMode();

	/** Retrieves the target of the CLEARCHAT. Might be a user name, if a user was purged, or empty, if the entire chat was purged
	 *
	 * @return Target of the CLEARCHAT, or empty if entire chat was cleared
	 */
	String getTarget();

	/** Retrieves the duration of the ban/purge. Only applies to a CLEARCHAT of type USER. <br>
	 * If the CLEARCHAT is of type {@link CLEARCHAT_MODE#COMPLETE}, this will always return -1. If it is of type {@link CLEARCHAT_MODE#USER}, it
	 * will return the length of the timeout, or -1 if it was a permanent ban.
	 * 
	 * @return Duration on the ban in seconds, or -1 if no duration was assigned.
	 */
	int getDuration();

	/**Retrieves the reason for the timout/ban/clear. Might be empty
	 *
	 * @return The reason for this CLEARCHAT. Might be empty
	 * @deprecated Twitch has removed the ability to get the ban reason from IRC, so this library cannot support getting
	 * ban reason anymore. This method will be removed in a future update.
	 */
	String getReason();
} public interface ClearChatBuilder {

	/**Constructs a new {@link ClearChat} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link ClearChat} object.
	 * Make sure that the COMMAND of the message equals "CLEARCHAT"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link ClearChat}, or <code>null</code> if a {@link ClearChat} could not be created
	 */
	public ClearChat build(TwitchMessage message);

    static ClearChatBuilder getDefault(){
        return new DefaultClearChatBuilder();
    }
} public interface ClearMsg extends AbstractType{
	/** Retrieves the message sender's username
	 *
	 * @return Message sender's username
	 */
	public String getSender();

	/** Retrieves the message id of the removed message. 
	 *  This matches the received message id returned on {@link TwitchMessage#getMessageID()}
	 * 
	 * @return The message id
	 */
	public String getTargetMsgId();

	/** Retrieves the contents of the removed message.
	 *
	 * @return The message contents
	 */
	public String getTargetMessageContent();
} public interface ClearMsgBuilder {

	/**Constructs a new {@link ClearMsg} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link ClearMsg} object.
	 * Make sure that the COMMAND of the message equals "CLEARMSG"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link ClearMsg}, or <code>null</code> if a {@link ClearMsg} could not be created
	 */
	public ClearMsg build(TwitchMessage message);

    static ClearMsgBuilder getDefault(){
        return new DefaultClearMsgBuilder();
    }
} public interface HostTarget extends AbstractType {
	
	/** Tells which MODE this HOSTTARGET has (START or STOP)
	 * 
	 * @return This {@link HOSTTARGET_MODE}
	 */
	public HOSTTARGET_MODE getMode();
	
	/** Tells us which channel we started hosting with this HOSTTARGET
	 * 
	 * @return Name of channel we started hosting
	 */
	public String getTarget();
	
	/** Tells us how many viewers this HOSTTARGET affected (MODE:START adds viewers, MODE:STOP removes viewers)
	 * 
	 * @return Amount of viewers we contribute/contributed to the target
	 */
	public int getViewerCount();
	
} public interface HostTargetBuilder {

    public static HostTargetBuilder getDefault() {
        return new DefaultHostTargetBuilder();
    }

	/**Constructs a new {@link HostTarget} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link HostTarget} object.
	 * Make sure that the COMMAND of the message equals "HOSTTARGET"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link HostTarget}, or <code>null</code> if a {@link HostTarget} could not be created
	 */
	public HostTarget build(TwitchMessage message);
} public interface Mode extends AbstractType{
	public static enum MODE_EVENT{ GAINED_MOD, LOST_MOD }

	/** {@link MODE_EVENT#GAINED_MOD} if {@code user} gained mod, {@link MODE_EVENT#LOST_MOD} if {@code user} lost mod
	 * 
	 * @return {@link MODE_EVENT} of this MODE
	 */
	public MODE_EVENT getEvent();
	
	/** Which user was affected by this MODE event
	 * 
	 * @return The user's name, in lower case letters
	 */
	public String getUser();
	
} public interface ModeBuilder {

    public static ModeBuilder getDefault() {
        return new DefaultModeBuilder();
    }

	/**Constructs a new {@link Mode} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link Mode} object.
	 * Make sure that the COMMAND of the message equals "MODE"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link Mode}, or <code>null</code> if a {@link Mode} could not be created
	 */
	public Mode build(TwitchMessage message);
} public interface Notice extends AbstractType{

	/** The {@link NOTICE_EVENT} type of this NOTICE 
	 * 
	 * @return The {@link NOTICE_EVENT} of this NOTICE
	 */
	public NOTICE_EVENT getEvent();
	
	/** The message that came with this NOTICE. Might contain useful information, such as number of hosts left this hour or if we receive an error notice.
	 * 
	 * @return The message
	 */
	public String getMessage();
	
	/** Fetches the raw Notice exactly as Twitch formats it. In case the {@link NOTICE_EVENT} is of type {@link NOTICE_EVENT#OTHER}, this
	 * field might be useful for checking what id this EVENT had.
	 * 
	 * @return The raw Notice ID
	 */
	public String getRawNoticeID();
} public interface NoticeBuilder {

    public static NoticeBuilder getDefault() {
        return new DefaultNoticeBuilder();
    }

	/**Constructs a new {@link Notice} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link Notice} object.
	 * Make sure that the COMMAND of the message equals "NOTICE"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link Notice}, or <code>null</code> if a {@link Notice} could not be created
	 */
	public Notice build(TwitchMessage message);
} public interface Roomstate extends AbstractType {

  /**
   * The chat language when broadcaster language mode is enabled, and empty otherwise. Might be empty, if this ROOMSTATE
   * had no information about it
   *
   * @return This ROOMSTATE's broadcasterLanguage (might be empty)
   */
  String getBroadcasterLanguage();

  /**
   * If 1, it means that R9K mode is enabled. 0 means it is disabled. -1 means that this ROOMSTATE did not mention r9k
   *
   * @return r9k mode status of this ROOMSTATE
   */
  int get9kMode();

  /**
   * If 1, it means that sub mode is enabled. 0 means it is disabled. -1 means that this ROOMSTATE did not mention
   * subMode
   *
   * @return sub mode status of this ROOMSTATE
   */
  int getSubMode();

  /**
   * If -1, it means that followers mode is disabled. 0 means it is enabled. If greater than 0, it means only users
   * following for at least the specified number of minutes can chat.
   *
   * @return followers mode status of this ROOMSTATE
   */
  int getFollowersMode();


  /**
   * If 1, it means that emote-only mode is enabled. 0 means it is disabled. -1 means that this ROOMSTATE did not
   * mention emote-only mode
   *
   * @return emote-only mode status of this ROOMSTATE
   */
  int getEmoteOnlyMode();

  /**
   * If greater than 0, it means that users must wait more than X seconds between posting messages. -1 means that this
   * ROOMSTATE did not mention slowMode
   *
   * @return slow mode status of this ROOMSTATE
   */
  int getSlowModeTimer();

} public interface RoomstateBuilder {

    public static RoomstateBuilder getDefault() {
        return new DefaultRoomstateBuilder();
    }

	/**Constructs a new {@link Roomstate} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link Roomstate} object.
	 * Make sure that the COMMAND of the message equals "ROOMSTATE"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link Roomstate}, or <code>null</code> if a {@link Roomstate} could not be created
	 */
	public Roomstate build(TwitchMessage message);
} public interface TwitchMessage extends AbstractEmoteMessage {

	/**Retrieves this message's tag segment. Should always starts with a @. Note that the
	 * Tag segment will look vastly different for different Twitch commands, and some won't
	 * even have a tag.
	 *
	 * @return The tag segment, or {@code ""} if no tag was present
	 */
	public String getTag();

	/**Retrieves the message's prefix.<br><br>
	 *
	 * A typical Twitch message looks something line this:<br>
	 * <code>:name!name@name.tmi.twitch.tv COMMAND #channel :message</code> <br><br>
	 *
	 * The prefix is the part before the first space. It usually only contains data about the sender of
	 * the message, but it might sometimes contain other information (PING messages for example just have PING as
	 * their prefix).<br><br>
	 *
	 * @return The messages prefix
	 */
	public String getPrefix();

	/**Retrieves the message's command.<br>
	 * The command tells us what action triggered this message being sent.<br><br>
	 *
	 * @return The message's command
	 */
	public String getCommand();

	/**Retrieves the message's target.<br>
	 * The target tells us whom the message is intended towards. It can be a user,
     * a channel, or something else (though mostly the channel).
     * <p>
	 * This segment is not always present.
	 *
	 * @return The message's target, or {@code ""} if no target
	 */
	public String getTarget();

	/**Retrieves the message's content.<br>
	 * The content is the commands parameters. Most often, this is the actual chat message, but it may be many
	 * other things for other commands.<br><br>
	 *
	 * This segment is not always present.
	 *
	 * @return The message's content, or {@code ""} if no content
	 */
	public String getContent();

    /**Tells whether this message was a cheer event or not.
     *
     * @return {@code true} if the message contains bits, <code>false</code> otherwise
     */
    public boolean isCheer();

    /**Fetches a list of all all cheers in this message. Each cheer is encapsulated in a {@link Cheer}.
	 * The list might be empty, if the message contained no cheers.
     *
	 * @return List of emotes (might be empty)
	 */
    public List<Cheer> getCheers();

    /**Fetches the total number of bits that this message contained.
     * This method is short-hand for:
     * <pre>
     * int bits = 0;
     * for(Cheer c : getCheers())
     *      bits += c.getBits();
     * return bits;
     * </pre>
     * @return number of bits
     */
    public int getBits();

    /**Fetches the {@link TagMap} that has parsed the message's tag into a key-value map.
     * For a list of different identifiers that can occur in a tag, check the {@link TwitchTags} class.
     */
    public TagMap getTagMap();
} public interface TwitchMessageBuilder {

	/**Constructs a new {@link TwitchMessage} object from a chat line received from Twitch.<br>
	 * A valid chat line has 2-5 segments:<br>
	 * <code>@TAG<optional> :PREFIX COMMAND TARGET<optional> :CONTENT<optional></code>
	 * <br><br>
	 * From this chat line, we create a {@link TwitchMessage}. If certain parts are not present, the corresponding
	 * <code>get</code> method on the {@link TwitchMessage} will return an empty string.
	 *
	 * @param chatLine The chat line, <b>exactly</b> as received from Twitch
	 * @return A {@link TwitchMessage}, or <code>null</code> if a {@link TwitchMessage} could not be created
	 */
	public TwitchMessage build(String chatLine);

    static TwitchMessageBuilder getDefault(){
        return new DefaultTwitchMessageBuilder();
    }
} public interface Usernotice extends AbstractEmoteMessage {

    /**Retrieves the message, as input by the user. This message might contain
     * emotes (see {@link #hasEmotes()} and {@link #getEmotes()}.
	 * It might also be empty, in which case, the message is {@code ""}
	 *
	 * @return The message. Might be {@code ""}
	 */
	public String getMessage();

	/**The system message contains the text which'll be printed in the Twitch
     * Chat on Twitch's side. It might look like this: <br>
	 * {@code system-msg=TWITCH_UserName\shas\ssubscribed\sfor\s6\smonths!;}.
     * <p>
	 * This is basically the message printed in chat to tell other viewers
     * what just occred (a raid, a subscription and so on).
     * <p>
	 * This method returns the system message like it looks from server side.
     * It will, however, replace all {@code \s} with spaces.
	 *
	 * @return The system message
	 */
	public String getSystemMessage();

    /**Tells whether this Usernotice is a subscription (or re-subscription) alert.
     *
     * @return {@code true} if this is a subscription alert
     */
    public boolean isSubscription();

    /**Retrieves the Subscription object. The Optional object wraps the
     * Subscription object (as an alternative to returning {@code null}).
     *
     * @return the Subscription
     */
    public Optional<Subscription> getSubscription();

    /**Tells whether this Usernotice is a raid alert.
     *
     * @return {@code true} if this is a raid alert
     */
    public boolean isRaid();

    /**Retrieves the Raid object. The Optional object wraps the
     * Raid object (as an alternative to returning {@code null}).
     *
     * @return the Raid
     */
    public Optional<Raid> getRaid();

    /**Tells whether this Usernotice is a ritual alert.
     *
     * @return {@code true} if this is a ritual alert
     */
    public boolean isRitual();

    /**Retrieves the Ritual object. The Optional object wraps the
     * Ritual object (as an alternative to returning {@code null}).
     *
     * @return the Ritual
     */
    public Optional<Ritual> getRitual();
} public interface UsernoticeBuilder {

	/**Constructs a new {@link Usernotice} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link Usernotice} object.
	 * Make sure that the COMMAND of the message equals "USERNOTICE"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link Usernotice}, or <code>null</code> if a {@link Usernotice} could not be created
	 */
	public Usernotice build(TwitchMessage message);

    static UsernoticeBuilder getDefault(){
        return new DefaultUsernoticeBuilder();
    }
} public interface TwitchUser {

    /**Retrieves this user's user name. This is the name the user logs in to
     * Twitch with
	 *
	 * @return The user's user name
	 */
	public String getUserName();

	/**Retrieves this user's display name, as displayed in Twitch chat
	 *
	 * @return The user's display name
	 */
	public String getDisplayName();

    /**Retrieves info whether this user is the owner of this channel or not
	 *
	 * @return {@code true} if the user is the owner, {@code false} if not
	 */
    public boolean isOwner();

	/**Retrieves info whether this user is a mod in this channel or not
	 *
	 * @return {@code true} if the user is mod, {@code false} if not
	 */
	public boolean isMod();

	/**Retrieves info whether this user has turbo or not
	 *
	 * @return {@code true} if the user has turbo, {@code false} if not
	 */
	public boolean isTurbo();

	/**Retrieves info whether this user is a sub to this channel or not
	 *
	 * @return {@code true} if the user is a sub, {@code false} if not
	 */
	public boolean isSub();

	/**Retrieves this users {@link USER_TYPE} <br>
	 * There are seven USER_TYPEs: OWNER, MOD, GLOBAL_MOD, ADMIN, STAFF, SUBSCRIBER and DEFAULT.
	 *
	 * @return The user's USER_TYPE
	 */
	public USER_TYPE getUserType();

	/**Retrieves this users display color, as seen in Twitch chat.<br>
	 * The color is a hexadecimal number.
	 *
	 * @return The users display color, as a hex number
	 */
	public int getColor();

	/**Retrieves the users set of badges in Twitch chat. A badge looks like this: <br>
	 * {@code broadcaster/1} <br><br>
	 *
	 * There are several different badges, such as {@code broadcaster/1}, {@code turbo/1} and so on. I do
	 * not know all of them explicitly, or what to do with them.
	 *
	 * TODO: Find out more about badges
	 *
	 * @return Arrays of strings, representing this users badges. Might be empty if user has none.
	 */
	public String[] getBadges();

	/**Retrieves this user's unique user ID. This ID is decided by Twitch, and will
	 * always be the same for the same user
	 *
	 * @return The users unique user ID
	 */
	public long getUserID();
} public interface TwitchUserBuilder {

	/**Constructs a new {@link TwitchUser} object, from a {@link TwitchMessage}<br><br>
	 *
	 * @param message The {@link TwitchMessage} which this user sent
	 * @return A {@link TwitchUser}, or <code>null</code> if no TwitchUser could be built
	 */
	public TwitchUser build(TwitchMessage message);

    static TwitchUserBuilder getDefault(){
        return new DefaultTwitchUserBuilder();
    }
} public interface Userstate extends AbstractType{
	
	/**Retrieves our display color, as a hex-number. <br>
	 * If we have no color set on Twitch's side, a semi-random color will be generated
	 * 
	 * @return Our display color
	 */
	public int getColor();
	
	/**Retrieves our display name, as seen in chat on Twitch
	 * 
	 * @return Our display name
	 */
	public String getDisplayName();
	
	/**Retrieves information on whether we are a mod in this channel or not.
	 *  
	 * @return <code>true</code> if we are mod
	 */
	public boolean isMod();
	
	/**Retrieves information on whether we are a sub in this channel or not.
	 *  
	 * @return <code>true</code> if we are sub
	 */
	public boolean isSub();
	
	/**Retrieves information on whether we have Turbo, or not
	 * 
	 * @return <code>true</code> if we have turbo
	 */
	public boolean isTurbo();
	
	/**Retrieves information on what type of user we are in this channel. See {@link USER_TYPE}
	 * 
	 * @return Our {@link USER_TYPE}
	 */
	public USER_TYPE getUserType();
	
	/**Retrieves the emote sets that are available to this account. You can uses the emote set's names to request information
	 * about those emotes from Twitch.<br><br>
	 * 
	 * For example, if we have emote set 0, we can request information about the emotes in that set by visiting:<br>
	 * <a href="https://api.twitch.tv/kraken/chat/emoticon_images?emotesets=0">https://api.twitch.tv/kraken/chat/emoticon_images?emotesets=0</a>
	 *  A request to that adress will return a JSON file with all emotes in that set.<br><br>
	 *  
	 * You can request information about several sets at once, by listing emote sets after one another separated by a comma ( , )<br>
	 * For example: <a href="https://api.twitch.tv/kraken/chat/emoticon_images?emotesets=0,12">https://api.twitch.tv/kraken/chat/emoticon_images?emotesets=0,12</a> 
	 * 
	 * @return Our emote sets
	 */
	public String[] getEmoteSets();

	/**Retrieves the users set of badges in Twitch chat. A badge looks like this: <br>
	 * {@code broadcaster/1} <br><br>
	 *
	 * There are several different badges, such as {@code broadcaster/1}, {@code turbo/1} and so on. I do
	 * not know all of them explicitly, or what to do with them.
	 *
	 * TODO: Find out more about badges
	 *
	 * @return Arrays of strings, representing this users badges. Might be empty if user has none.
	 */
	public String[] getBadges();

} public interface UserstateBuilder {

    public static UserstateBuilder getDefault() {
        return new DefaultUserstateBuilder();
    }

	/**Constructs a new {@link Userstate} object from a {@link TwitchMessage}, received from Twitch. The user
	 * is responsible for making sure that this message can actually be made into a {@link Userstate} object.
	 * Make sure that the COMMAND equals "USERSTATE"
	 *
	 * @param message The message we received from Twitch
	 * @return A {@link Userstate}, or <code>null</code> if a {@link Userstate} could not be created
	 */
	public Userstate build(TwitchMessage message);
}
import com.gikk.twirk.events.TwirkListener;
import com.gikk.twirk.types.clearChat.ClearChat;
import com.gikk.twirk.types.clearChat.ClearChatBuilder;
import com.gikk.twirk.types.clearMsg.ClearMsg;
import com.gikk.twirk.types.clearMsg.ClearMsgBuilder;
import com.gikk.twirk.types.hostTarget.HostTarget;
import com.gikk.twirk.types.hostTarget.HostTargetBuilder;
import com.gikk.twirk.types.mode.Mode;
import com.gikk.twirk.types.mode.ModeBuilder;
import com.gikk.twirk.types.notice.Notice;
import com.gikk.twirk.types.notice.NoticeBuilder;
import com.gikk.twirk.types.roomstate.Roomstate;
import com.gikk.twirk.types.roomstate.RoomstateBuilder;
import com.gikk.twirk.types.twitchMessage.TwitchMessage;
import com.gikk.twirk.types.twitchMessage.TwitchMessageBuilder;
import com.gikk.twirk.types.usernotice.Usernotice;
import com.gikk.twirk.types.usernotice.UsernoticeBuilder;
import com.gikk.twirk.types.users.TwitchUser;
import com.gikk.twirk.types.users.TwitchUserBuilder;
import com.gikk.twirk.types.users.Userstate;
import com.gikk.twirk.types.users.UserstateBuilder;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

		outThread.end();
		inThread.end();

		try { socket.close(); }
		catch (IOException ignored) {  }

		try { reader.close(); }
		catch (IOException ignored) {  }

		try { writer.close(); }
		catch (IOException ignored) {  }
	}


	private boolean doConnect() throws IOException{
		// Log on to the server.
		writer.write("PASS " + pass + "\r\n");
        writer.write("NICK " + nick + "\r\n");
        writer.write("USER " + nick + " 8 * : GikkBot\r\n");
        writer.flush( );


        // Read lines from the server until it tells us we have connected.
        String line;
        while ((line = reader.readLine()) != null) {
            logger.debug("IN  " + line);

            //When we get a message containing 004, we have successfully logged in
            if (line.contains("004")) {
                return true;
            }
            else if (line.contains("Error logging in")) {
                return false;
            }
        }

		//We hit this return if the reader timed out, or we reached the end of stream
        return false;
	}

	/**Gives us the appropriate Twitch capacities, such as seeing JOIN/PART messages,
	 * to send Twitch commands (such as .timeout, .mod and so on) and to see
	 * users tags (such as display color)
	 */
	private void addCapacities(){
		serverMessage("CAP REQ :twitch.tv/membership");
		serverMessage("CAP REQ :twitch.tv/commands");
		serverMessage("CAP REQ :twitch.tv/tags");
	}

    /**Tells the OutputThread how long we should wait, at minimum, in between
     * each message sent to Twitch.
     *
     * @param millis the delay
     */
    void setOutputMessageDelay(int millis){
        this.outThread.setMessageDelay(millis);
    }

	void incommingMessage(String line){
		//PING is a bit strange, so we need to handle it separately. And also, we want to respond to a ping
		//before we do anything else.
		if ( line.contains("PING") ) {

    		// A PING contains the message "PING MESSAGE", and we want to reply with MESSAGE as well
    		// Hence, we reply "PONG MESSAGE" . That's where the substring(5) comes from bellow, we strip
    		//out everything but the message
			logger.debug("IN  " + line);

    		serverMessage("PONG " + line.substring(5) ); //Remove the "PING " part, and send the rest back
    		return;
		}

		//Call all the appropriate listeners for the given message.
		synchronized (listeners) {
			//First, we call all onAnything messages
			for(TwirkListener l : listeners ) {
                l.onAnything( line );
            }

			TwitchMessage message = twitchMessageBuilder.build(line);

            //This message is a reply for a capacity request. Just ignore it
            String s = message.getCommand();
            switch (s) {
                case "JOIN":
                {
                    String userName = parseUsername( message.getPrefix() );
                    for(TwirkListener l : listeners ) {
                        l.onJoin( userName );
                    }
                    break;
                }
                case "MODE":
                {
                    Mode mode = modeBuilder.build(message);
                    for(TwirkListener l : listeners ) {
                        l.onMode( mode );
                    }
                    break;
                }
                case "PART":
                {
                    String userName = parseUsername( message.getPrefix() );
                    for(TwirkListener l : listeners ) {
                        l.onPart( userName );
                    }
                    break;
                }
                case "CLEARCHAT":
                {
                    ClearChat clearChat = clearChatBuilder.build(message);
                    for(TwirkListener l : listeners ) {
                        l.onClearChat(clearChat);
                    }
                    break;
                }
                case "CLEARMSG":
                {
                    ClearMsg clearMsg = clearMsgBuilder.build(message);