TabsOfAvabur

Tabs the channels it finds in chat, can be sorted, with notif for new messages

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         TabsOfAvabur
// @namespace    Reltorakii.magic
// @version      3.1
// @description  Tabs the channels it finds in chat, can be sorted, with notif for new messages
// @author       Reltorakii
// @match        https://*.avabur.com/game.php
// @grant        none
// ==/UserScript==
/* jshint -W097 */
/* jshint -W043 */
"use strict";

(function($) {

    var options                 = {
        scriptSettings  : {
            purge                       : true,
            channel_remove              : false,
            preview                     : true,
            preview_reset               : false,
            group_wires                 : false,
            at_username                 : true,
            join_channel_link           : true,
            auto_join                   : false,
            profile_tooltip_nickname    : true,
            profile_tooltip_mention     : true,
            profile_tooltip_quickscope  : true
        },
        channelsSettings    : {
            channelMerger       : {
                groups              : [],
                mapping             : {},
                defaultChannels     : {}
            },
            mutedChannels   : []
        },
        version: "3.1"
    };
    var groupsMap               = {};
    var channelLog              = {};
    var mainChannelID           = "2";
    var currentChannel          = "Main";
    var ServerMessagesChannel   = "SML_325725_2338723_CHC";
    var CMDResposeChannel       = "CMDRC_4000_8045237_CHC";
    var WhispersChannel         = "UW_7593725_3480021_CHC";
    var WiresChannel            = "WC_0952340_3245901_CHC";
    var MergedChannelsGroup     = "MCG_105704_4581101_CHC";

    var GlobalChannel           = 1000000000;
    var EventChannel            = 2000000000;
    var chatDirection           = "up";

    var scriptChannels          = [ServerMessagesChannel, CMDResposeChannel, WhispersChannel, WiresChannel];

    var showedMoTD              = false;
    var lastMoTDContent         = "";

    var showingReconnectMsg     = false;
    var internalUpdateUrl       = "https://api.github.com/repos/edvordo/TabsOfAvabur/contents/TabsOfAvabur.user.js";

    var hovering;
    var hoveringOverTab;

    var checkForUpdateTimer     = 0;

    function returnCustomID(channel, resolved, cname, on) {
        var obj =  {
            cID: channel, 
            res: resolved, 
            name: cname, 
            on: typeof on !== "undefined" ? on : name
        };
        return obj;
    }

    function resolveChannelID(channel) {
        var channelID;
        var origChannelName = channel;
        var resolved = true;
        if (channel === "GLOBAL") {
            channel = "Global";
        } else if (channel === "CLAN") {
            channel = "Clan";
        } else if (channel.substr(0,4) === "AREA") {
            channel = "Area";
        } else if (channel === "HELP") {
            channel = "Help";
        } else if (channel === "STAFF") {
            channel = "Staff";
        } else if (channel === "TRADE") {
            channel = "Trade";
        } else if (channel === "Market") {
            return returnCustomID(CMDResposeChannel, true, "");//  info channel changes this later
        } else if (channel === "Whispers Log") {
            return returnCustomID(WhispersChannel, true, channel, origChannelName);
        } else if (channel === "Wires Log") {
            return returnCustomID(WiresChannel, true, channel, origChannelName);
        } else if (channel === "Server Messages") {
            return returnCustomID(ServerMessagesChannel, true, channel, origChannelName);
        } else if (channel.match(/^Level:\s+[0-9]+/)) {
            return returnCustomID(CMDResposeChannel, true, "", origChannelName);//  info channel changes this later
        }
        var map = {
            "Global": "GLOBAL",
            "Clan": "CLAN",
            "Area": "AREA",
            "Help": "HELP",
            "Staff": "STAFF",
            "Trade": "TRADE"
        };
        if (typeof map[origChannelName] !== "undefined") {
            origChannelName = map[origChannelName];
        }

        channelID = 0;
        $("select#chatChannel option").each(function(i,e){
            var n = $(e).attr("name");
            if (n==="channel"+channel) {
                channelID = $(e).attr("value");
            }
        });
        if (options.channelsSettings.channelMerger.groups.indexOf(origChannelName) !== -1) {
            channelID = MergedChannelsGroup + "_MCGID_" + groupsMap[origChannelName];
        }

        if (origChannelName == "GLOBAL"){
            channelID = GlobalChannel;
        }
        if (origChannelName == "Event"){
            channelID = EventChannel;
        }

        if (channelID === 0) {
            resolved = false;
            channelID = "2";// Main
        }

        return returnCustomID(channelID, resolved, channel, origChannelName);
    }

    function resolveChannelColor(channelID, channelName) {
        var color = "";
        try {
            color = $(".chatChannel[data-id=\"" + channelName + "\"]").css("background-color");
        } catch (e) {
            color = "";
        }
        if (color === "" || typeof color === "undefined") {
            $(".chatChannel").each(function(i,e){
                if ($(e).attr("data-id") === channelName) {
                    color = $(e).css("background-color");
                }
            });
        }
        if (channelID === ServerMessagesChannel) {
            color = "#007f23";
        } else if (channelID === CMDResposeChannel) {
            color = "#317D80";
        } else if (channelID === WhispersChannel) {
            color = "#DE3937"; //FF3
        } else if (channelID === WiresChannel) {
            color = "#39DE37"; //FF3
        }
        return color;
    }

    function updateChannelList(channel) {
        var tab = $("#channelTab" + channel.channelID);
        if (tab.length === 0) {
            if (channel.muted) {
                return;
            }
            $("<div>")
                .attr("id", "channelTab" + channel.channelID)
                .attr("data-channel", channel.channelID)
                .addClass("border2 ui-element channelTab")
                .css({
                    color: channel.channelColor
                })
                .appendTo("#channelTabList");
            tab = $("#channelTab" + channel.channelID);
        }
        var channelTabLabel = "#"+channel.channelName;
        tab.text(channelTabLabel).css({color: channel.channelColor});
        if (channel.newMessages && !channel.muted) {

            if ($(".Ch"+channel.channelID+"Badge").length === 0) {
            var badge = $("<span>")
                .addClass("ChBadge")
                .addClass("border2")
                .addClass("Ch"+channel.channelID+"Badge")
                .text(channel.newMessagesCount)
                .appendTo("#channelTab"+channel.channelID);
            } else {
                $(".Ch"+channel.channelID+"Badge").text(channel.newMessagesCount);
            }
        }
        if (channel.muted) {
            $("<span>")
                .addClass("ChBadge fa fa-times border2 ui-element")
                .appendTo("#channelTab"+channel.channelID);
        }
    }

    function addSettingsTab() {
        $("<div>")
            .attr("id", "ToASettings")
            .addClass("border2 ui-element ToASettings")
            .prependTo("#channelTabList");
        $("<span>")
            .addClass("fa")
            .addClass("fa-cogs")
            .css({
                color: "#ffd700",
                fontWeight: 500
            })
            .appendTo("#ToASettings");
    }

    function randomInt(min, max) {
        return Math.round( Math.random() * ( max - min ) ) + min;
    }

    function randomColor() {
        var color = "#";
        for (var i = 0; i < 6; i++) {
            color += Math.floor(Math.random()*15).toString(16);
        }
        return color;
    }

    function randomName(min, max) {
        var a = "aeiou".split("");
        var b = "rtzpsdfghklmnbvc".split("");
        var l = randomInt(min, max);
        var name = "";
        for (var i = 0; i < l; i++)
        {
            var charset = i % 2 === 0 ? a : b;
            if ( i === 0 )
            {
                charset = Math.random() < 0.5 ? a : b;
            }
            var letter = charset[randomInt(0, charset.length - 1)];
            name += i === 0 ? letter.toUpperCase() : letter;
        }
        return name;
    }

    function ucfirst(str) {
        var result  = "";
        var first   = str.charAt(0).toUpperCase();

        return first + str.substr(1);
    }

    function loadDependencies() {
        //<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
        $("<link>")
            .attr({
                rel: "stylesheet",
                href: "//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"
            })
            .appendTo("head");
    }

    function prepareHTML() {
        $("<div>")
            .attr("id", "channelTabListWrapper")
            .insertBefore("#chatMessageListWrapper");
        $("<div>")
            .attr("id", "channelTabList")
            .appendTo("#channelTabListWrapper");

        /**
         * Preview channel
         */
         $("<div>")
            .attr("id", "channelPreviewWrapper")
            .addClass("border2")
            .addClass("ui-element")
            .appendTo("body");

        $("<h5>")
            .css("text-align", "center")
            .appendTo("#channelPreviewWrapper");

        $("<div>")
            .attr("id", "channelPreviewActions")
            .appendTo("#channelPreviewWrapper");

        $("<span>")
            .addClass("border2 ui-element fa fa-check sapphire cpa")
            .attr("id", "CPAReset")
            .attr("title", "Mark as read")
            .appendTo("#channelPreviewActions");

        $("<span>")
            .addClass("border2 ui-element fa fa-eraser emerald cpa")
            .attr("id", "CPAPurge")
            .attr("title", "Clear channel of all messages")
            .appendTo("#channelPreviewActions");

        $("<span>")
            .addClass("border2 ui-element fa fa-unlink ruby cpa")
            .attr("id", "CPARemove")
            .attr("title", "Clear the channel and remove it from tabs\nIf any new messages pop into it, it will come back.")
            .appendTo("#channelPreviewActions");

        $("<div>")
            .attr("id", "channelPreviewContent")
            .appendTo("#channelPreviewWrapper");

        $("<div>")
            .attr("id", "channelPreviewMessages")
            .css({
                padding:"2px",
            })
            .appendTo("#channelPreviewContent");
        $("#channelPreviewContent").mCustomScrollbar({scrollInertia: 250,mouseWheel:{scrollAmount: 40}});

        /**
         * context menu
         */

         $("<div>")
            .attr("id", "channelTabContextMenu")
            .addClass("ui-element navSection")
            .appendTo("body");

        $("<a>")
            .attr("id", "chTabCTMenuMute")
            .text("Mute channel")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-bell-slash titanium")
            .prependTo("#chTabCTMenuMute");

        $("<a>")
            .attr("id", "chTabCTMenuUnMute")
            .text("Un-mute channel")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-bell platinum")
            .prependTo("#chTabCTMenuUnMute");

        $("<a>")
            .attr("id", "chTabCTMenuReset")
            .text("Mark as read")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-check sapphire")
            .prependTo("#chTabCTMenuReset");

        $("<a>")
            .attr("id", "chTabCTMenuLast")
            .text("Show history")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-history materials")
            .prependTo("#chTabCTMenuLast");

        $("<a>")
            .attr("id", "chTabCTMenuPurge")
            .text("Purge messages")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-eraser emerald")
            .prependTo("#chTabCTMenuPurge");

        $("<a>")
            .attr("id", "chTabCTMenuRemove")
            .text("Remove from tabs")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-unlink ruby")
            .prependTo("#chTabCTMenuRemove");

        $("<a>")
            .attr("id", "chTabCTMenuLeave")
            .text("Leave channel")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-arrow-right diamond")
            .prependTo("#chTabCTMenuLeave");

        $("<a>")
            .attr("id", "chTabCTMenuColor")
            .text("Change color")
            .addClass("cctmButton")
            .appendTo("#channelTabContextMenu");

        $("<span>")
            .addClass("ui-element fa fa-crosshairs crystals")
            .prependTo("#chTabCTMenuColor");


        $("#channelTabContextMenu").hide();

        /**
         * settings
         */
        $("<div>")
            .attr("id", "ToASettingsWindow")
            .addClass("border2 ui-element")
            .appendTo("body");

        $("<h5>")
            .css("text-align", "center")
            .text("TabsOfAvabur v"+options.version+" - Settings")
            .appendTo("#ToASettingsWindow");

        $("<div>")
            .attr("id","ToASWMenu")
            .appendTo("#ToASettingsWindow");

        var t = $("<div>")
            .addClass("col-sm-6 text-center");

        var l = t.clone().appendTo("#ToASWMenu");
        var r = t.clone().appendTo("#ToASWMenu");

        $("<button>")
            .attr("type", "button")
            .attr("id", "ToAScriptOptions")
            .addClass("btn btn-primary btn-block")
            .text("Script options")
            .appendTo(l);

        $("<button>")
            .attr("type", "button")
            .attr("id", "ToAChannelMerger")
            .addClass("btn btn-primary btn-block")
            .text("(WIP) Channel Manager")
            .appendTo(r);

        $("<div>").addClass("clearfix").appendTo("#ToASettingsWindow");

        $("<div>")
            .attr("id", "ToASettingsWindowContent")
            .appendTo("#ToASettingsWindow");

        $("<div>")
            .attr("id", "ToASettingsScriptSettings")
            .appendTo("#ToASettingsWindowContent");

        var st  = $("<h6>").addClass("text-center");
        var t2  = $("<label>");
        var t2a = $("<input>").attr({"type":"checkbox"}).addClass("settingsChanger");
        var t2w = t.clone().removeClass("text-center");

        st.clone().text("Script settings").appendTo("#ToASettingsScriptSettings");
        // purge channel
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Allow channel message purging")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","purge")
                            .prop("checked", options.scriptSettings.purge)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");
        // purge and remove
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Allow removing channel form tabs")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","channel_remove")
                            .prop("checked", options.scriptSettings.channel_remove)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // preview
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Preview channel on tab hover")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","preview")
                            .prop("checked", options.scriptSettings.preview)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // mark read
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Allow marking channels as read")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","preview_reset")
                            .prop("checked", options.scriptSettings.preview_reset)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // mark read
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Group wires into their own channel")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","group_wires")
                            .prop("checked", options.scriptSettings.group_wires)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // @mention
        t2w.clone()
            .append(
                t2.clone()
                    .text(" Make @username clickable")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","at_username")
                            .prop("checked", options.scriptSettings.at_username)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // /join channel password
        t2w.clone()
            .append(
                t2.clone()
                    .html(" Make '/join channel' clickable. <span class='fa fa-info-circle ToATooltip' title='After you click on the link, the chat message will be filled with a /join channel text.' data-toggle='tooltip' data-placement='top' data-html='true'></span>")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","join_channel_link")
                            .prop("checked", options.scriptSettings.join_channel_link)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // /join channel password
        t2w.clone()
            .append(
                t2.clone()
                    .html(" Autojoin clicked channel. <span class='fa fa-info-circle ToATooltip' title='This is designed to work with the previous option to replace the /join <a>channel</a> message.<br>If this option is enabled, the prefilled message to join a channel will be automatically sent.' data-toggle='tooltip' data-placement='top' data-html='true'></span>")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","auto_join")
                            .prop("checked", options.scriptSettings.auto_join)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // profileOptionsTooltip - Nickname
        t2w.clone()
            .append(
                t2.clone()
                    .html(" Enable Ni[c]kname shortcut")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","profile_tooltip_nickname")
                            .prop("checked", options.scriptSettings.profile_tooltip_nickname)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // profileOptionsTooltip - @mention
        t2w.clone()
            .append(
                t2.clone()
                    .html(" Enable @m[e]ntion shortcut")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","profile_tooltip_mention")
                            .prop("checked", options.scriptSettings.profile_tooltip_mention)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        // profileOptionsTooltip - Nickname
        t2w.clone()
            .append(
                t2.clone()
                    .html(" Enable [Q]uickscope shortcut")
                    .prepend(
                        t2a.clone()
                            .attr("data-setting","profile_tooltip_quickscope")
                            .prop("checked", options.scriptSettings.profile_tooltip_quickscope)
                    )
            )
            .appendTo("#ToASettingsScriptSettings");

        $("<div>").addClass("clearfix").appendTo("#ToASettingsScriptSettings");

        $("<div>")
            .attr("id", "ToASettingsChannelMerger")
            .appendTo("#ToASettingsWindowContent");

        st.clone().text("Muted channels").appendTo("#ToASettingsChannelMerger");

        /**
         * muted channels content added on settings window open
         */

        $("<div>")
            .attr("id", "ToASChMMutedChannelsHolder")
            .addClass("border2 ui-element ToASChannelsHolder")
            .appendTo("#ToASettingsChannelMerger");

        // clearfix muted channels
        $("<div>").addClass("clearfix").appendTo("#ToASettingsWindow");

        /**
         * channel merger content added on setting window open
         */
        st.clone().text("Channel Merger").appendTo("#ToASettingsChannelMerger");

        // holder for all channels - script created ones
        $("<div>")
            .attr("id", "ToASChMMergedChannelsHolder")
            .addClass("border2 ui-element ToASChannelsHolder incsort")
            .appendTo("#ToASettingsChannelMerger")
            .before(t2.clone().text("Available Channels:"));

        // holder for groups
        $("<div>")
            .attr("id", "ToASChMMergedChannelsGroupsHolder")
            .addClass("ui-element ToASChannelsHolder")
            .appendTo("#ToASettingsChannelMerger")
            .before();
        var chgl = t2.clone().text("Channel Groups:").insertBefore("#ToASChMMergedChannelsGroupsHolder");
        $("<button>").addClass("fa fa-plus btn btn-primary emerald pull-right btn-xs").attr("id", "ToASChMAddGroup").insertAfter(chgl);

        // clearfix channel merger
        $("<div>").addClass("clearfix").appendTo("#ToASettingsChannelMerger");

        // clearfix settings window
        $("<div>").addClass("clearfix").appendTo("#ToASettingsWindow");

        $("<div>")
            .attr("id", "ToASettingsSaved")
            .text("Settings have been saved and are applied")
            .addClass("text-center small")
            .appendTo("#ToASettingsWindow");

        // close button
        $("<span>")
            .attr("id", "ToASettingsWindowClose")
            .addClass("fa fa-times border2 ui-element")
            .appendTo("#ToASettingsWindow");

        /**
         * profile tooltip extras
         */
        var ToAExtraDivider = $("<span>").text(" · ");

        ToAExtraDivider.clone().addClass("ToAPONickname").toggleClass("hidden", !options.scriptSettings.profile_tooltip_nickname).appendTo("#profileOptionTooltip");
        $("<a>").addClass("ToAPONickname").toggleClass("hidden", !options.scriptSettings.profile_tooltip_nickname).text("Ni[c]kname").attr("id", "profileOptionNick").appendTo("#profileOptionTooltip");

        ToAExtraDivider.clone().addClass("ToAPOMention").toggleClass("hidden", !options.scriptSettings.profile_tooltip_mention).appendTo("#profileOptionTooltip");
        $("<a>").addClass("ToAPOMention").toggleClass("hidden", !options.scriptSettings.profile_tooltip_mention).text("@m[e]ntion").attr("id", "profileOptionAt").appendTo("#profileOptionTooltip");

        ToAExtraDivider.clone().addClass("ToAPOQuickscope").toggleClass("hidden", !options.scriptSettings.profile_tooltip_quickscope).appendTo("#profileOptionTooltip");
        $("<a>").addClass("ToAPOQuickscope").toggleClass("hidden", !options.scriptSettings.profile_tooltip_quickscope).text("[Q]uickscope").attr("id", "profileOptionQuickScope").appendTo("#profileOptionTooltip");

        // init
        $("#ToASettingsWindow").hide();
        $("#ToASettingsScriptSettings").hide();
        $("#ToASettingsChannelMerger").hide();
        $("#ToASettingsSaved").hide();
        $(".ToATooltip").tooltip();
        $("#ToASettingsWindow").draggable({handle:"h5"});
        /**
         * CSS
         */
        $("<style>").text(""+
            "#channelTabListWrapper{margin-bottom: -1px;position: relative;}#channelTabList{overflow: hidden;border-radius: 4px 4px 0 0;font-size: 9pt;}\n"+
            ".ToASettings, .channelTab{cursor: pointer;margin: 2px 2px 0 2px;border-radius: 4px 4px 0 0;display: inline-block;padding: 2px 5px;position:relative;}\n"+
            "#chatMessageList li:not(.processed){display: none;}\n"+
            "/*#chatMessageList li.processed{display: list-item;}*/\n"+
            ".ChBadge{display:inline-block;margin-left:3px;padding:1px 4px;font-size:7pt;vertical-align:top;border-color:green!important;color:#fff !important;}\n"+
            ".muted-badge{position:absolute;left:5px;top:5px;}\n"+
            ".mCSB_scrollTools.mCSB_scrollTools_horizontal{top:15px!important;}\n"+
            ".mCSB_horizontal.mCSB_inside>.mCSB_container{margin-bottom: 0 !important;}\n"+
            "#channelPreviewWrapper{position:absolute;font-size:9pt;min-width:350px;max-width:500px;background-color:rgba(0,0,0,.75)!important;}\n"+
            "#channelPreviewContent{max-height: 250px;overflow-y: hidden;}\n"+
            "#channelPreviewActions{position:absolute;right:2px;top:2px;}\n"+
            ".cpa{display:inline-block;margin-left:2px;padding: 1px 3px;font-size:9pt;vertical-align:top;cursor:pointer;}\n"+
            "#channelTabContextMenu{position:absolute;width:175px;background-color:rgba(0,0,0,.75)!important;}\n"+
            ".cctmButton{text-align:left!important;}\n"+
            "#ToASettingsWindow{position:absolute!important;width:50%;min-width: 500px;top:150px;left:25%;background-color:rgba(0,0,0,.75)!important;z-index:150;}\n"+
            ".cctmButton>span{margin: 0 15px 0 5px;font-size:8.5pt;padding:2px;}\n"+
            "#channelTabContextMenu .cctmButton {display:block;width:100%;border-left:0;}\n"+
            "#ToASettingsWindowContent label{font-size:10pt;}\n"+
            "#ToASettingsWindowContent {padding-top:5px;}\n"+
            "#ToASettingsWindowClose{position:absolute;right:2px;top:2px;color:#f00;padding:1px 4px;cursor:pointer;}\n"+
            ".ToASChannelsHolder{padding: 2px;margin:3px auto;width:97%;}\n"+
            ".ChMChannelWrapper{display:inline-block;margin:1px 2px;padding:1px 4px;font-size:10pt;}\n"+
            ".ChMMChX{margin-right:4px;padding:1px 2px;cursor:pointer;}\n"+
            "#ToASettingsWindow .tooltip{width:350px;}\n"+
            "#ToASettingsWindow .tooltip-inner{max-width:100%;}\n"+
            ".hand{curson: pointer;}\n"+
            "#ToASChMAddGroup, .ToASChMChGRemove{margin-top: 0;}\n"+
            ".incsort{border-radius: 0 !important; margin: 3px 1px; padding: 2px;}\n"+
            ".chTabSelected {background-image: " + $("#navigationWrapper > h5").css("background-image")+" !important;}\n"+
            "#ToASChMMergedChannelsGroupsHolder > .incsort > span:nth-of-type(1) {border-left-width: 7px !important;}\n"+
            "@media screen and (max-width:768px){#ToASettingsWindow{left:5%;}}")
        .appendTo("body");
    }

    var SSN = 0;
    function saveOptions() {
        clearTimeout(SSN);
        var opts = JSON.stringify(options);
        localStorage.setItem("ToAOPTS", opts);
        $("#ToASettingsSaved").show();
        SSN = setTimeout(function(){
            $("#ToASettingsSaved").fadeOut();
        }, 3E3);
    }

    function changeSetting(e) {
        var setting = $(e).attr("data-setting");
        options.scriptSettings[setting] = $(e).prop("checked");
        var match = setting.match("^profile_tooltip_([a-z]+)");
        if (match !== null) {
            var POOption = ucfirst(match[1]);
            $(".ToAPO"+POOption).toggleClass("hidden");
        }
        saveOptions();
    }

    function resetUnreadCount() {
        var channelID                           = hoveringOverTab;
        channelLog[channelID].newMessages       = false;
        channelLog[channelID].newMessagesCount  = 0;
        updateChannelList(channelLog[channelID]);
        $("#channelPreviewWrapper").hide();
        $("#channelTabContextMenu").hide();
    }

    function purgeChannel(andRemove,confirmToo) {
        andRemove       = typeof andRemove==="undefined"?options.scriptSettings.channel_remove:andRemove;
        confirmToo      = typeof confirmToo==="undefined"?false:confirmToo;
        var channelID   = hoveringOverTab;
        var channelName = channelLog[channelID].channelName;
        var confirmText = "Are you sure you want purge the \""+channelName+"\" channel"+(andRemove?" and remove it from tabs":"")+"?\nThis only affects your screen.";
        if (confirmToo || window.confirm(confirmText)){
            $(".chc_"+channelID).remove();
            resetUnreadCount();
            if (andRemove) {
                $("#channelTab"+channelID).remove();
                //delete channelLog[channelID];
                $("#channelTabMain").click();
                $("#channelPreviewWrapper").hide();
            }

        }
    }

    function loadOptions(){
        var stored = localStorage.getItem("ToAOPTS");
        try {
            var parsed = JSON.parse(stored);
            if (typeof parsed.scriptSettings !== "undefined"){
                if (typeof parsed.scriptSettings.purge !== "undefined") {
                    options.scriptSettings.purge = !!parsed.scriptSettings.purge;
                }
                if (typeof parsed.scriptSettings.channel_remove !== "undefined") {
                    options.scriptSettings.channel_remove = !!parsed.scriptSettings.channel_remove;
                }
                if (typeof parsed.scriptSettings.preview !== "undefined") {
                    options.scriptSettings.preview = !!parsed.scriptSettings.preview;
                }
                if (typeof parsed.scriptSettings.preview_reset !== "undefined") {
                    options.scriptSettings.preview_reset = !!parsed.scriptSettings.preview_reset;
                }
                if (typeof parsed.scriptSettings.group_wires !== "undefined") {
                    options.scriptSettings.group_wires = !!parsed.scriptSettings.group_wires;
                }
                if (typeof parsed.scriptSettings.at_username !== "undefined") {
                    options.scriptSettings.at_username = !!parsed.scriptSettings.at_username;
                }
                if (typeof parsed.scriptSettings.join_channel_link !== "undefined") {
                    options.scriptSettings.join_channel_link = !!parsed.scriptSettings.join_channel_link;
                }
                if (typeof parsed.scriptSettings.auto_join !== "undefined") {
                    options.scriptSettings.auto_join = !!parsed.scriptSettings.auto_join;
                }
                if (typeof parsed.scriptSettings.profile_tooltip_nickname !== "undefined") {
                    options.scriptSettings.profile_tooltip_nickname = !!parsed.scriptSettings.profile_tooltip_nickname;
                }
                if (typeof parsed.scriptSettings.profile_tooltip_mention !== "undefined") {
                    options.scriptSettings.profile_tooltip_mention = !!parsed.scriptSettings.profile_tooltip_mention;
                }
                if (typeof parsed.scriptSettings.profile_tooltip_quickscope !== "undefined") {
                    options.scriptSettings.profile_tooltip_quickscope = !!parsed.scriptSettings.profile_tooltip_quickscope;
                }
            }
            if (typeof parsed.channelsSettings !== "undefined" && typeof parsed.version !== "undefined") {
                if (typeof parsed.channelsSettings.mutedChannels !== "undefined" && Array.isArray(parsed.channelsSettings.mutedChannels)) {
                    options.channelsSettings.mutedChannels = parsed.channelsSettings.mutedChannels;
                }
                if (typeof parsed.channelsSettings.channelMerger !== "undefined") {
                    if (typeof parsed.channelsSettings.channelMerger.groups !== "undefined" && Array.isArray(parsed.channelsSettings.channelMerger.groups)) {
                        for (var ccg in parsed.channelsSettings.channelMerger.groups) {
                            var groupName = parsed.channelsSettings.channelMerger.groups[ccg];
                            if (typeof groupName === "string" && options.channelsSettings.channelMerger.groups.indexOf(groupName) === -1) {
                                options.channelsSettings.channelMerger.groups.push(groupName);
                                groupsMap[groupName] = randomName(3,5) + "_" + randomInt(5,9);
                            }
                        }
                    }
                    if (typeof parsed.channelsSettings.channelMerger.mapping !== "undefined" && typeof parsed.channelsSettings.channelMerger.mapping === "object") {
                        options.channelsSettings.channelMerger.mapping = parsed.channelsSettings.channelMerger.mapping;
                    }
                    if (typeof parsed.channelsSettings.channelMerger.defaultChannels !== "undefined" && typeof parsed.channelsSettings.channelMerger.defaultChannels === "object") {
                        options.channelsSettings.channelMerger.defaultChannels = parsed.channelsSettings.channelMerger.defaultChannels;
                    }
                }
            }
            //$.extend(true, options, parsed || {});
            saveOptions();
        } catch(e) {
            localStorage.removeItem("ToAOPTS");
            // console.log(e);
        }
    }

    function createChannelEntry(newChannel, newChannelID, newChannelColor) {
        channelLog[newChannelID] = {
            channelName: newChannel,
            channelID: newChannelID,
            channelColor: newChannelColor,
            messages: 0,
            newMessages: false,
            newMessagesCount: 0,
            muted: options.channelsSettings.mutedChannels.indexOf(newChannel) !== -1
        };
    }

    function loadAllChannels() {
        $("#chatChannel option").each(function(i,e){
            var channelName     = $(e).text();
            var channelInfo     = resolveChannelID(channelName);
            var channelID       = channelInfo.cID;
            var channelColor    = resolveChannelColor(channelID, channelInfo.name);
            if (typeof channelLog[channelID] === "undefined") {
                createChannelEntry(channelInfo.on, channelID, channelColor);
            }
        });
        if (typeof channelLog[GlobalChannel] === "undefined") {
            createChannelEntry("GLOBAL", GlobalChannel, resolveChannelColor(GlobalChannel, "Global"));
        }
        if (typeof channelLog[EventChannel] === "undefined") {
            createChannelEntry("Event", EventChannel, resolveChannelColor(EventChannel, "Event"));
        }
    }

    function quickScopeUser(){
        if (!options.scriptSettings.profile_tooltip_quickscope) {
            return false;
        }
        $("#chatMessage").text("/whois "+$("#profileOptionTooltip").attr("data-username"));
        $("#chatSendMessage").click();
        $("#profileOptionTooltip").hide();
        setTimeout(function(){$("#channelTab"+CMDResposeChannel).click();},1000);
    }

    function mentionUser() {
        if (!options.scriptSettings.profile_tooltip_mention) {
            return false;
        }
        $("#chatMessage").append(" @"+$("#profileOptionTooltip").attr("data-username")).focus();
        $("#profileOptionTooltip").hide();
    }

    function nicknameUser() {
        if (!options.scriptSettings.profile_tooltip_nickname) {
            return false;
        }
        var username = $("#profileOptionTooltip").attr("data-username");
        $.confirm({
            "title"     : "Nickname for "+username,
            "message"   : "<input type=\"text\" id=\"ToASPONicknameName\" style=\"width:100%;\" placeholder=\"Leave blank to unnickname\">",
            "buttons"   : {
                "Nickname"       : {
                    "class"     : "green",
                    "action"    : function() {
                        var newNick = $("#ToASPONicknameName").val();
                        if (newNick.match(/^\s*$/)) {
                            $("#chatMessage").text("/unnickname "+username);
                        } else {
                            $("#chatMessage").text("/nickname "+username+" "+newNick);
                        }
                        $("#chatSendMessage").click();
                    }
                },
                "Cancel"       : {
                    "class"     : "red",
                    "action"    : function() {
                    }
                }
            }
        });
        setTimeout(function() {
            $("#ToASPONicknameName").val("").focus();
        }, 500);
    }

    function isScriptChannel(channelID) {
        return scriptChannels.indexOf(channelID) !== -1;
    }

    function updateGroupName() {
        var newName     = $(this).val();
        var groupID     = $(this).attr("data-gnid");
        var origName    = options.channelsSettings.channelMerger.groups[groupID];
        var origGID     = groupsMap[origName];
        delete groupsMap[origName];
        groupsMap[newName] = origGID;
        options.channelsSettings.channelMerger.groups[groupID] = newName;
        $(this).parent().attr("data-group", newName);
        for (var x in options.channelsSettings.channelMerger.mapping) {
            if (options.channelsSettings.channelMerger.mapping[x] === origName) {
                options.channelsSettings.channelMerger.mapping[x] = newName;
            }
        }
        var groupChannelID = MergedChannelsGroup + "_MCGID_" + groupsMap[newName];
        if (typeof channelLog[groupChannelID] !== "undefined") {
            channelLog[groupChannelID].channelName = newName;
            updateChannelList(channelLog[groupChannelID]);
        }
        saveOptions();
    }

    function addChannelGroup(i, name) {
        var mcgw    = $("<div>").addClass("border2 incsort input-group");

        var mcgigb  = $("<div>").addClass("input-group-btn");

        var mcgdb   = $("<button>").addClass("ToASChMChGRemove btn btn-primary btn-xs ruby");
        var mcgn    = $("<input>").attr({type:"text",name:"mcg_cn"}).addClass("ToASChMmcgName");

        var mcgID = MergedChannelsGroup + "_MCGID_" + groupsMap[name];
        var wrapper = mcgw.clone().attr({"id": mcgID,"data-group": name}).appendTo("#ToASChMMergedChannelsGroupsHolder");

        var igb = mcgigb.clone().appendTo(wrapper);
        mcgdb.clone().attr("data-gnid", i).html("<i class=\"fa fa-times\"></i>").appendTo(igb);
        mcgn.clone().val(name).attr("data-gnid", i).appendTo(wrapper);
    }

    function handleAjaxSuccess(a,res,req,json) {
        var decide = "";
        var valid = ["up", "down"];
        if (json.hasOwnProperty("cs")) {
            if (valid.indexOf(json.cs) !== -1) {
                
                decide = json.cs;
            }
        } else if (json.hasOwnProperty("p") && json.p.hasOwnProperty("chatScroll")) {
            if (valid.indexOf(json.p.chatScroll) !== -1) {
                decide = json.p.chatScroll;
            }
        }
        if (decide !== "") {
            chatDirection = decide;
        }
    }

    function versionCompare(v1, v2) {
        var regex   = new RegExp("(\.0+)+");
            v1      = v1.replace(regex, "").split(".");
            v2      = v2.replace(regex, "").split(".");
        var min     = Math.min(v1.length, v2.length);

        var diff = 0;
        for (var i = 0; i < min; i++) {
            diff = parseInt(v1[i], 10) - parseInt(v2[i], 10);
            if (diff !== 0) {
                return diff;
            }
        }

        return v1.length - v2.length;
    }

    function checkForUpdate() {
        var version = "";
        $.get(internalUpdateUrl).done(function(res){
            var match = atob(res.content).match(/\/\/\s+@version\s+([^\n]+)/);
                version = match[1];

            if (versionCompare(options.version, version) < 0) {
                var message = "<li class=\"chat_notification\">TabsOfAvabur has been updated to version "+version+"! <a href=\"https://github.com/edvordo/TabsOfAvabur/raw/master/TabsOfAvabur.user.js\" target=\"_blank\">Update</a> | <a href=\"https://github.com/edvordo/TabsOfAvabur/releases\" target=\"_blank\">Changelog</a></li>";
                if (chatDirection === "up") {
                    $("#chatMessageList").prepend(message);
                } else {
                    $("#chatMessageList").append(message);
                    $("#chatMessageWrapper").mCustomScrollbar("scrollTo", "bottom");
                }
            } else {
                checkForUpdateTimer = setTimeout(checkForUpdate, 24*60*60*1000);
            }
        });
    }

    function loadMessages(t) {
        if ($("#chatChannel option").length > 2) {
            $("#chatMessageList li:not(.processed)").each(function(i,e){
                var plainText       = $(e).text();
                // lets get rid of staff stuff
                plainText           = plainText.replace(/^\[X\]\s*/, "");
                // now clean up spaces
                plainText           = plainText.replace(/\s+/g, " ");
                // default message format [11:11:11] [Channel] (optional) the rest of the message
                var defaultMsg      = plainText.match(/^\[([^\]]+)\]\s*(\[([^\]]+)\])?\s*(.*)/);
                // clan MoTD: [11 Nov, 1111] Clan Message of the Day:
                var isClanMoTD      = plainText.replace(/^\[[0-9]+\s+[a-zA-Z]+\,\s*[0-9]+\]\s*/, "").indexOf("Clan Message of the Day:") === 0;
                // clan MoTD: [11 Nov, 1111] Message of the Day:
                var isRoAMoTD       = plainText.replace(/^\[[0-9]+\s+[a-zA-Z]+\,\s*[0-9]+\]\s*/, "").indexOf("Message of the Day:") === 0;
                // Staff Server Messages [11:11:11] [ Whatever the hell. ]
                var isServerMsg     = plainText.match(/^\[[^\]]+\]\s*\[\s+.*\s+]$/);
                // whisper detection
                var isWhisper       = plainText.match(/^\[[^\]]+\]\s*Whisper\s*(to|from)\s*([^:]+)/);
                    isWhisper       = isWhisper && $(this).closest("li").find("span:eq(2)").text().indexOf("Whisper") === 0;
                // wire detection
                var isWire          = plainText.match(/^\[[^\]]+\]\s*(You|[a-zA-Z]+)\s*wired\s*.*\s*(you|[a-zA-Z]+)\.$/);
                // [11:11:11] Username sent a whatever to you.

                var isChatNotif     = $(e).children(".chat_notification").length > 0 || $(e).hasClass("chat_notification");
                var isChatReconnect = $(e).attr("id") === "websocket_reconnect_line";

                var channel = "";
                if (currentChannel.match(/^[0-9]+$/)){
                    channel = channelLog[currentChannel].channelName;
                } else if (currentChannel.indexOf(MergedChannelsGroup) === 0) {
                    channel = channelLog[currentChannel].channelName;
                } else if (scriptChannels.indexOf(currentChannel) !== -1) {
                    channel = channelLog[currentChannel].channelName;
                } else {
                    channel = currentChannel;
                }
                // var channel         = currentChannel=="Main" ? currentChannel : ;
                var channelInfo     = resolveChannelID(channel);

                if (defaultMsg !== null) {
                    channel         = typeof defaultMsg[3] === "undefined" ? "Main" : defaultMsg[3];
                    if (channel !== "Main") {
                        var validate = $(this).closest("li").find("span:eq(2)").text() === "[";
                        var quickscopeinfo = channel.match(/^Level:\s+[0-9]+/);
                        if (!validate && quickscopeinfo === null) {
                            channel = "Main";
                        }
                    }
                    channelInfo     = resolveChannelID(channel);
                }
                if (isClanMoTD) {
                    channel         = "CLAN";
                    channelInfo     = resolveChannelID(channel);
                } else if (isServerMsg){
                    channel         = "Server Messages";
                    channelInfo     = resolveChannelID(channel);
                } else if (isWhisper){
                    channel         = "Whispers Log";
                    channelInfo     = resolveChannelID(channel);
                } else if (isWire && options.scriptSettings.group_wires){
                    channel         = "Wires Log";
                    channelInfo     = resolveChannelID(channel);
                }
                var channelID       = channelInfo.cID;
                    channel         = channelInfo.on;
                if (
                    channelID !== CMDResposeChannel &&
                    channelID !== ServerMessagesChannel &&
                    channelID !== WiresChannel &&
                    ( isChatNotif || isChatReconnect)
                ) {

                    channelID       = channelInfo.cID;
                }
                // console.log("chinfo:");
                // console.log(channelInfo);
                if (channelID === CMDResposeChannel){
                    channel         = "Info Channel";
                }
                var channelColor    = resolveChannelColor(channelID, channelInfo.name);

                if (typeof options.channelsSettings.channelMerger.mapping[channel] !== "undefined") {
                    var groupName   = options.channelsSettings.channelMerger.mapping[channel];
                    var groupID     = options.channelsSettings.channelMerger.groups.indexOf(groupName);
                    channelID       = MergedChannelsGroup + "_MCGID_" + groupsMap[groupName];
                    channel         = groupName;
                    channelColor    = randomColor();
                }
                 // console.log("cl",currentChannel, "cID", channelID);
                if (currentChannel != channelID){
                    $(e).addClass("hidden");
                } /*else {
                    $(e).show();
                }*/
                $(e).addClass("processed");
                $(e).addClass("chc_" + channelID);
                if (typeof channelLog[channelID] === "undefined") {
                    createChannelEntry(channel, channelID, channelColor);
                    /*channelLog[channelID] = {
                        channelName: channel,
                        channelID: channelID,
                        channelColor: channelColor,
                        messages: 0,
                        newMessages: false,
                        newMessagesCount: 0,
                        muted: options.channelsSettings.mutedChannels.indexOf(channel) !== -1
                    };*/
                }
                if (channelID != currentChannel){
                    channelLog[channelID].newMessages = true;
                    channelLog[channelID].newMessagesCount++;
                }
                channelLog[channelID].messages++;
                if (options.channelsSettings.mutedChannels.indexOf(channel) !== -1){
                    $(e).remove();
                }

                if (options.scriptSettings.at_username) {
                    $(e).html($(e).html().replace(/\@([a-zA-Z]+)/g,"@<a class=\"profileLink\">$1</a>"));
                }

                if (options.scriptSettings.join_channel_link) {
                    $(e).html($(e).html().replace(/\/join\s+([^\s]+)\s*([^\s<]+)?/, "/join <a class=\"joinChannel\">$1</a> <span class=\"jcPWD\">$2</span>"));
                }

                if (plainText.match(/tabs\s+of\s+avabur/i) !== null) {
                    clearTimeout(checkForUpdateTimer);
                    checkForUpdateTimer = setTimeout(checkForUpdate, randomInt(30, 120) * 1000);
                }

                updateChannelList(channelLog[channelID]);
            });
        }

        if (typeof t === "undefined") {
            setTimeout(loadMessages, 500);
        }
        if ($("#chatWrapper>div:nth-child(2)").attr("id") === "chatMessageWrapper") {
            $("#channelTabListWrapper").insertBefore("#chatMessageListWrapper");
        }
    }

    function init() {
        loadOptions();
        loadDependencies();
        prepareHTML();
        addSettingsTab();
        loadMessages();

        $("#channelTabListWrapper").mCustomScrollbar({axis:"x",advanced:{autoExpandHorizontalScroll:true}});
        $("#channelTabList").sortable({items:".channelTab",distance: 5});
        $("#channelTabList").disableSelection();
        setTimeout(function(){$("#channelTabList > div:nth-child(2)").click();},2000);
        checkForUpdateTimer = setTimeout(checkForUpdate,30000);
    }

    $(document).on("ajaxSuccess", handleAjaxSuccess);

    $(document).on("change", ".settingsChanger", function(e){
        changeSetting(this);
    });

    $(document).on("click", ".channelTab", function(e){
        $(".channelTab").removeClass("chTabSelected");
        var channelID = $(this).attr("data-channel");
        channelLog[channelID].newMessages = false;
        channelLog[channelID].newMessagesCount = 0;
        updateChannelList(channelLog[channelID]);
        // $(".processed").hide();
        $("#chatMessageList > li:not(.hidden)").addClass("hidden");
        $(".chc_"+channelID).removeClass("hidden");
        $("#channelTab"+channelID).addClass("chTabSelected");
        $("#channelPreviewWrapper").hide();
        currentChannel = channelID;
        if (channelID.match(/^[0-9]+$/) === null) {
            var groupName = channelLog[channelID].channelName;
            if (options.channelsSettings.channelMerger.groups.indexOf(groupName) !== -1) {
                if (typeof options.channelsSettings.channelMerger.defaultChannels[groupName] !== "undefined") {
                    channelID = resolveChannelID(options.channelsSettings.channelMerger.defaultChannels[groupName]).cID;
                }
            }
        }
        var channelOption = $("#chatChannel option[value="+channelID+"]");
        if (channelOption.length > 0){
            $("#chatChannel").val(channelID);
        }
        if (chatDirection === "down") {
            setTimeout(function(){
                $("#chatMessageListWrapper").mCustomScrollbar("scrollTo",  "bottom");
            }, 500);
        }
    });

    $(document).on("click", "#CPAReset, #chTabCTMenuReset", function(){
        resetUnreadCount();
    });

    $(document).on("click", "#CPAReset, #chTabCTMenuLast", function(){
        var channelName = channelLog[hoveringOverTab].channelName;
        var msg = "/last "+channelName;
        if (channelName === "CLAN") {
            msg = "/c /last";
        } else if (options.channelsSettings.channelMerger.groups.indexOf(channelName) !== -1) {
            if (typeof options.channelsSettings.channelMerger.defaultChannels[channelName] !== "undefined") {
                msg = "/last " + options.channelsSettings.channelMerger.defaultChannels[channelName];
            }
        } else if (channelName === "Whispers Log") {
            msg = "/w /last";
        } else if (scriptChannels.indexOf(hoveringOverTab) !== -1) {
            return false;
        }
        $("#chatMessage").text(msg);
        $("#chatSendMessage").click();
    });

    $(document).on("click", "#CPAPurge, #chTabCTMenuPurge", function(){
        var confirmToo = $(this).attr("id") === "chTabCTMenuPurge";
        purgeChannel(false, confirmToo);
    });

    $(document).on("click", "#CPARemove, #chTabCTMenuRemove", function(){
        var confirmToo = $(this).attr("id") === "chTabCTMenuRemove";
        purgeChannel(true, confirmToo);
    });

    $(document).on("click", "#chTabCTMenuLeave", function(){
        var channelName = channelLog[hoveringOverTab].channelName;
        purgeChannel(true, true);
        $("#chatMessage").text("/leave " + channelName);
        $("#chatSendMessage").click();
    });

    $(document).on("click", "#chTabCTMenuColor", function(){
        if (hoveringOverTab.indexOf(MergedChannelsGroup) !== -1) {
            var color = randomColor();
            channelLog[hoveringOverTab].channelColor = color;
            updateChannelList(channelLog[hoveringOverTab]);
        } else {
            $.alert("Tab color change failed! Please try again!", "Group tab color change");
        }
    });

    $(document).on("click", "#chTabCTMenuMute", function(){
        if (typeof hoveringOverTab === "undefined"){
            return;
        }
        var channel = channelLog[hoveringOverTab].channelName;
        if (options.channelsSettings.mutedChannels.indexOf(channel) === -1) {
            options.channelsSettings.mutedChannels.push(channel);
            saveOptions();
        }
        channelLog[hoveringOverTab].muted = true;
        updateChannelList(channelLog[hoveringOverTab]);
    });

    $(document).on("click", "#chTabCTMenuUnMute", function(){
        if (typeof hoveringOverTab === "undefined"){
            return;
        }
        var channel = channelLog[hoveringOverTab].channelName;
        var pos = options.channelsSettings.mutedChannels.indexOf(channel);
        if (pos !== -1) {
            options.channelsSettings.mutedChannels.splice(pos,1);
            saveOptions();
        }
        channelLog[hoveringOverTab].muted = false;
        updateChannelList(channelLog[hoveringOverTab]);
    });

    $(document).on("mouseover", ".channelTab", function(e){
        clearTimeout(hovering);
        var channelID       = $(this).attr("data-channel");
        hoveringOverTab     = channelID;
        if (!options.scriptSettings.preview){
            return;
        }
        var channelName     = channelLog[channelID].channelName;

        var channelPreviewWrapper = $("#channelPreviewWrapper");

        var channelTabHolder    = $(this);

        var cssOptions = {
            top: ($(this).offset().top + 25)+"px"
        };
        var previewContent = "There are no new messages in this channel!";
        if (channelLog[channelID].newMessages === true) {
            var previewMessages = [];
            $(".chc_"+channelID).each(function(i,e){
                if (i < channelLog[channelID].newMessagesCount){
                    previewMessages.push($(e).html());
                }
            });
            previewContent = previewMessages.join("<br>");
        }

        $("#channelPreviewMessages").html(previewContent);

        if ($(this).offset().left > $(document).width() / 2){
            cssOptions.left = ($(this).offset().left - channelPreviewWrapper.width() + 50)+"px";
        } else {
            cssOptions.left = ($(this).offset().left + 50)+"px";
        }
        channelPreviewWrapper
            .css(cssOptions)
            .children("h5")
                .text("'"+channelName+"' preview");

        if (options.scriptSettings.preview_reset){
            $("#CPAReset").show();
        } else {
            $("#CPAReset").hide();
        }
        if (options.scriptSettings.purge){
            $("#CPAPurge").show();
        } else {
            $("#CPAPurge").hide();
        }
        if (options.scriptSettings.channel_remove){
            $("#CPARemove").show();
        } else {
            $("#CPARemove").hide();
        }
    });

    $(document).on("mouseover", function(e){
        clearTimeout(hovering);
        if (typeof hoveringOverTab !== "undefined" && typeof channelLog[hoveringOverTab] !== "undefined") {

            var channelTab              = $("#channelTab" + hoveringOverTab);
            var channelPreviewWrapper   = $("#channelPreviewWrapper");
            var shouldShow              = channelLog[hoveringOverTab].newMessages === true;
            var OpenAndKeep             = $(e.target).closest(channelTab).length || $(e.target).closest(channelPreviewWrapper).length;
            var delay                   = OpenAndKeep ? 500 : 250;
            hovering = setTimeout(function(){
                if (options.scriptSettings.preview && OpenAndKeep && shouldShow) {
                    channelPreviewWrapper.show(0, function(){
                        if (chatDirection === "down") {
                            $("#channelPreviewContent").mCustomScrollbar("scrollTo",  "bottom");
                        }
                    });

                    
                } else {
                    channelPreviewWrapper.hide();
                }
            }, delay);
        }
    });

    $(document).on("contextmenu", ".channelTab", function(e){
        e.preventDefault();
        var cssOptions = {
            top: e.pageY+"px"
        };

        if ($(this).offset().left > $(document).width() / 2){
            cssOptions.left = (e.pageX - $(this).width())+"px";
        } else {
            cssOptions.left = e.pageX+"px";
        }

        if (options.scriptSettings.preview_reset){
            $("#chTabCTMenuReset").show();
        } else {
            $("#chTabCTMenuReset").hide();
        }
        if (options.scriptSettings.purge){
            $("#chTabCTMenuPurge").show();
        } else {
            $("#chTabCTMenuPurge").hide();
        }
        if (options.scriptSettings.channel_remove){
            $("#chTabCTMenuRemove").show();
        } else {
            $("#chTabCTMenuRemove").hide();
        }

        if (options.channelsSettings.mutedChannels.indexOf(channelLog[hoveringOverTab].channelName) !== -1){
            $("#chTabCTMenuUnMute").show();
            $("#chTabCTMenuMute").hide();
        } else {
            $("#chTabCTMenuMute").show();
            $("#chTabCTMenuUnMute").hide();
        }

        if (hoveringOverTab.match(/^[a-z]+/i)) {
            $("#chTabCTMenuLeave").hide();
            if (hoveringOverTab.indexOf(MergedChannelsGroup) !== -1) {
                $("#chTabCTMenuColor").show();
            } else {
                $("#chTabCTMenuColor").hide();
            }
        } else {
            $("#chTabCTMenuColor").hide();
            $("#chTabCTMenuLeave").show();
        }

        if (scriptChannels.indexOf(hoveringOverTab) !== -1 && hoveringOverTab !== WhispersChannel) {
            $("#chTabCTMenuLast").hide();
        } else {
            $("#chTabCTMenuLast").show();
        }
        // $("#chTabCTMenuColor").hide();

        $("#channelTabContextMenu").css(cssOptions).show();
        $("#channelPreviewWrapper").hide();
        return false;
    });

    $(document).on("click", "#ToASettings", function(){
        $("#modalBackground").show();
        $("#ToASettingsWindow").show();
        loadAllChannels();
        
        /**
         * load muted channel
         */

        var mchw    = $("<span>").addClass("ChMChannelWrapper border2");
        var mchx    = $("<span>").addClass("ChMMChX ui-element fa fa-times ruby");

        $("#ToASChMMutedChannelsHolder").html("");
        $("#ToASChMMergedChannelsHolder").html("");
        $("#ToASChMMergedChannelsGroupsHolder").html("");
        var channelName = "";
        for (var i in options.channelsSettings.mutedChannels) {
                channelName = options.channelsSettings.mutedChannels[i];
            var holder      = mchw.clone().append(channelName).appendTo("#ToASChMMutedChannelsHolder");
            mchx.clone().attr("data-channel", channelName).prependTo(holder);
        }
        channelName = "";

        $("#ToASChMMergedChannelsGroupsHolder").html("");
        for (var j in options.channelsSettings.channelMerger.groups){
            var mcggn = options.channelsSettings.channelMerger.groups[j];
            addChannelGroup(j, mcggn);
        }
        for (var channelID in channelLog) {
            if (!channelID.match(/^[0-9]+$/)) {
                continue;
            }
            var channelInfo     = channelLog[channelID];
                channelName     = channelInfo.channelName;
            var channelBlob     = mchw.clone().attr("data-channel", channelName).text(channelName);
            if (typeof options.channelsSettings.channelMerger.mapping[channelName] !== "undefined") {
                var grouppedInto    = options.channelsSettings.channelMerger.mapping[channelName];
                var mcgGroupID      = options.channelsSettings.channelMerger.groups.indexOf(grouppedInto);
                    mcgGroupID      = MergedChannelsGroup + "_MCGID_" + groupsMap[grouppedInto];
                if (options.channelsSettings.channelMerger.defaultChannels[grouppedInto] === channelName) {
                    channelBlob.insertAfter("#"+mcgGroupID+" > input");
                } else {
                    channelBlob.appendTo("#"+mcgGroupID);
                }
            } else {
                channelBlob.appendTo("#ToASChMMergedChannelsHolder");
            }
        }
        channelName = "";
        $(".incsort").sortable({
            items: "span",
            connectWith: ".incsort",
            receive: function(i,e) {
                    channelName = $(e.item[0]).attr("data-channel");
                var groupName   = $(this).attr("data-group");
                if (typeof groupName === "undefined") {
                    delete options.channelsSettings.channelMerger.mapping[channelName];
                } else {
                    options.channelsSettings.channelMerger.mapping[channelName] = groupName;
                }
                saveOptions();
            },
            update: function(i,e){
                var groupName   = $(this).attr("data-group");
                if (typeof groupName !== "undefined") {
                    var channels = $(i.target).children("span");
                    var channelName = $(channels[0]).attr("data-channel");
                    options.channelsSettings.channelMerger.defaultChannels[groupName] = channelName;
                    saveOptions();
                } // else branch makes no sense :)
            }
        }).disableSelection();
    });

    $(document).on("click", ".ChMMChX", function(){
        var channel             = $(this).attr("data-channel");
        var channelID           = resolveChannelID(channel).cID;
        channelLog[channelID].muted  = false;
        updateChannelList(channelLog[channelID]);
        var pos = options.channelsSettings.mutedChannels.indexOf(channel);
        if (pos !== -1) {
            options.channelsSettings.mutedChannels.splice(pos,1);
        }
        $(this).parent().fadeOut("slow", function(){
            $(this).remove();
        });
        saveOptions();
    });

    $(document).on("click", ".joinChannel", function(){
        // trim(",");
        var chn = $(this).text().replace(/^,+|,+$/gm,"");
        $("#chatMessage").text("/join "+ chn);
        var pwd = $(this).parent().find(".jcPWD").text();
        $("#chatMessage").append(" " + pwd);
        if (options.scriptSettings.auto_join) {
            $("#chatSendMessage").click();
        }
    });

    $(document).on("click", function(e){
        $("#channelTabContextMenu").hide();
        var settings = $("#ToASettingsWindow");
        if (
            !$(e.target).closest("#ToASettingsWindow").length &&
            !$(e.target).closest("#ToASettings").length &&
            !$(e.target).closest("#confirmOverlay").length &&
            !$(e.target).closest(".replenishStamina").length || 
            $(e.target).closest("#ToASettingsWindowClose").length) {

                settings.hide();
                $("#ToASettingsChannelMerger").hide();
                $("#ToASettingsScriptSettings").hide();
            if ($(e.target).closest("#ToASettingsWindowClose").length) {
                $("#modalBackground").fadeOut();
            }
        }
    });

    $(document).on("click", "#ToAScriptOptions, #ToAChannelMerger", function(){
        var id = $(this).attr("id");
        if (id === "ToAScriptOptions") {
            $("#ToASettingsChannelMerger").slideUp(function(){
                $("#ToASettingsScriptSettings").slideDown();
            });
        } else {
            $("#ToASettingsScriptSettings").slideUp(function(){
                $("#ToASettingsChannelMerger").slideDown();
            });
        }
    });

    $(document).on("click", "#profileOptionQuickScope", quickScopeUser);
    $(document).on("click", "#profileOptionAt", mentionUser);
    $(document).on("click", "#profileOptionNick", nicknameUser);

    $(document).on("keydown", function(e){
        var keys = {
            Q: 81, // [Q]uickscope
            C: 67, // Ni[c]kname
            E: 69 // @m[e]ntion
        };
        var key = e.which;
        if ($("#profileOptionTooltip").css("display")==="block") {

            if (key === keys.Q) {
                quickScopeUser();
            } else if (key === keys.E) {
                mentionUser();
                e.preventDefault();
            } else if (key === keys.C) {
                nicknameUser();
            }
        }
    });

    // on blur ... hmm
    $(document).on("change", ".ToASChMmcgName", updateGroupName);

    $(document).on("click", "#ToASChMAddGroup", function(){
        $.confirm({
            "title"     : "New Group Name",
            "message"   : "<input type=\"text\" id=\"ToASChMNewgroupName\" style=\"width:100%;\">",
            "buttons"   : {
                "Create"       : {
                    "class"     : "green",
                    "action"    : function() {
                        var groupName = $("#ToASChMNewgroupName").val();
                        if (groupName.match(/^\s*$/)){
                            groupName = randomName(7,13);
                        }
                        options.channelsSettings.channelMerger.groups.push(groupName);
                        groupsMap[groupName] = randomName(3,5) + "_" + randomInt(5,9);
                        $("#ToASettings").click();
                    }
                },
                "Cancel"       : {
                    "class"     : "red",
                    "action"    : function() {
                    }
                }
            }
        });
        $("#ToASChMNewgroupName").focus();
    });

    $(document).on("click", ".ToASChMChGRemove", function() {
        var elem = $(this);
        $.confirm({
            "title"     : "Group Delete Confirmation",
            "message"   : "Are you sure you want to remove this channel group?",
            "buttons"   : {
                "Yes"       : {
                    "class"     : "green",
                    "action"    : function() {
                        var groupID = elem.attr("data-gnid");

                        var groupName = options.channelsSettings.channelMerger.groups[groupID];

                        for (var x in options.channelsSettings.channelMerger.mapping) {
                            if (options.channelsSettings.channelMerger.mapping[x] === groupName) {
                                delete options.channelsSettings.channelMerger.mapping[x];
                            }
                        }

                        options.channelsSettings.channelMerger.groups.splice(groupID, 1);

                        var groupChannelID = MergedChannelsGroup + "_MCGID_" + groupsMap[groupName];
                        $("#channelTab"+groupChannelID).remove();
                        delete channelLog[groupChannelID];
                        delete groupsMap[groupName];
                        delete options.channelsSettings.channelMerger.defaultChannels[groupName];
                        $("#chatMessageList li").attr("class", "");
                        saveOptions();
                        $("#channelTabList > div:nth-child(2)").click();
                        loadMessages("reload");
                        $("#ToASettings").click();
                    }
                },
                "No"       : {
                    "class"     : "red",
                    "action"    : function() {
                    }
                }
            }
        });
    });

    init();
}(jQuery));