--
-- Created by IntelliJ IDEA.
-- User: RJ
-- Date: 03/02/14
-- Time: 09:28
-- To change this template use File | Settings | File Templates.
--

require "ISUI/ISPanel"
require "ISUI/ISRichTextPanel"
require "ISUI/ISButton"

ISChat = ISPanel:derive("ISChat");
ISChat.lines = {};
ISChat.maxLine = 50;
ISChat.toggleInvisibleTimer = 300;
ISChat.invisibleTimer = ISChat.toggleInvisibleTimer;

function ISChat:initialise()
    ISPanel.initialise(self);
end

function ISChat:createChildren()
    self.chatText = ISRichTextPanel:new(16, getCore():getScreenHeight() - 400, 500,200);
    self.chatText:initialise();
    self.chatText.background = false;
    self.chatText:setAnchorBottom(true);
    self.chatText:setAnchorRight(true);
    self.chatText.marginTop = 2
    self.chatText.marginBottom = 0
    self.chatText.onRightMouseUp = self.onRightMouseUp_chatText
    self.chatText.render = ISChat.render_chatText
    self.chatText.maxLines = 500
    self.moreinfo = self.chatText:wrapInCollapsableWindow();
    self.moreinfo.minimumHeight = 90
    self.moreinfo.minimumWidth = 200
    self.moreinfo:setDrawFrame(false);
    self.moreinfo:addToUIManager();
    self.chatText:setWidth(self.moreinfo:getWidth());
--    self.chatText:setHeight(self.moreinfo:getHeight()-16);
--    self.moreinfo:setHeight(self.moreinfo:getHeight() + 20);
--    self.chatText:setY(16);
--    self.moreinfo:setY(-16);
    self.chatText.autosetheight = false;

    local inset = 2
    local EdgeSize = 5 -- must match UITextBox2.EdgeSize
    local fontHgt = getTextManager():getFontFromEnum(UIFont.Medium):getLineHeight()
    local height = EdgeSize * 2 + fontHgt
    self.textEntry = ISTextEntryBox:new("", inset, self.moreinfo:getHeight() - 8 - inset - height, 500 - inset * 2, height);
    self.textEntry.font = UIFont.Medium
    self.textEntry:initialise();
    self.textEntry:instantiate();
    self.textEntry.backgroundColor = {r=0, g=0, b=0, a=0.0};
    self.textEntry.borderColor = {r=1, g=1, b=1, a=0.0};
    self.textEntry:setHasFrame(true)
    self.textEntry:setVisible(false);
    self.textEntry:setAnchorTop(false);
    self.textEntry:setAnchorBottom(true);
    self.textEntry:setAnchorRight(true);
    self.textEntry.onCommandEntered = ISChat.onCommandEntered;
    self.textEntry.onPressDown = ISChat.onPressDown;
    self.textEntry.onPressUp = ISChat.onPressUp;
    self.textEntry.onOtherKey = ISChat.onOtherKey
--    self.textEntry:addToUIManager();
    self.chatText:setHeight(self.chatText:getHeight() - self.textEntry:getHeight() - inset * 2)
    self.chatText:addScrollBars();
    self.chatText.vscroll.background = false;
    self.chatText:ignoreHeightChange()
    self.moreinfo:addChild(self.textEntry)
    self.mutedUsers = {}
end

function ISChat:prerender()
ISChat.instance = self
--    self.textEntry:setX(self.moreinfo.x + 20);
--    self.textEntry:setY(self.moreinfo.y + 155);
    local mouseOver = self.moreinfo.mouseOver or self.moreinfo.moving or
        self.moreinfo.resizeWidget.resizing or self.moreinfo.resizeWidget2.resizing or
        false
    self.moreinfo:setDrawFrame(mouseOver)
    if mouseOver then
        ISChat.invisibleTimer = 100
    end

    if ISChat.invisibleTimer > 0 then
        ISChat.invisibleTimer = ISChat.invisibleTimer -1;
        local a = 1 - getCore():getOptionChatTransparency() / 10
        if mouseOver then
            self.moreinfo.backgroundColor.a = math.max(a, 0.8)
        else
            self.moreinfo:drawRect(0, 0, self.moreinfo:getWidth(), self.moreinfo:getHeight(), a, 0, 0, 0);
        end
    elseif self.textEntry:getIsVisible() == false then
--        self.textEntry:clear();
--        self.textEntry:unfocus();
        self.moreinfo:setVisible(false);
    end
    if self.servermsg then
        self:drawTextCentre(self.servermsg, getCore():getScreenWidth() / 2, getCore():getScreenHeight() / 2 - 200, 1, 0.1, 0.1, 1, UIFont.Cred1);
        self.servermsgTimer = self.servermsgTimer - 1;
        if self.servermsgTimer < 0 then
            self.servermsg = nil;
            self.servermsgTimer = 0;
        end
    end
end

function ISChat:render_chatText()
    self:setStencilRect(0, 0, self.width, self.height)
    ISRichTextPanel.render(self)
    self:clearStencilRect()
end

function ISChat:onRightMouseUp_chatText(x, y)
    local context = ISContextMenu.get(0, self:getAbsoluteX() + self:getXScroll() + x, self:getAbsoluteY() + self:getYScroll() + y)
    context:addOption(getText("UI_chat_Clear"), ISChat.instance, ISChat.onContextClear)
end

function ISChat:onContextClear()
    ISChat.lines = {}
    self.chatText.text = ""
    self.chatText:paginate()
end

function ISChat:onCommandEntered()
    local command = ISChat.instance.textEntry:getText();

    ISChat.instance.logIndex = 0;
    if command and command ~= "" then
        local newLog = {};
        table.insert(newLog, command);
        for i,v in ipairs(ISChat.instance.log) do
            table.insert(newLog, v);
            if i > 20 then
                break;
            end
        end
        ISChat.instance.log = newLog;
    end

    ISChat.instance.textEntry:clear();
    ISChat.instance.textEntry:unfocus();
    ISChat.instance.textEntry:setText("");
    ISChat.instance.textEntry:setVisible(false);
    if not command or command == "" then
        return;
    end
    local commandProcessed, isShout, isWhisper = false, false, false;
    if luautils.stringStarts(command, "/all") and getServerOptions():getBoolean("GlobalChat") then
        local message = luautils.trim(string.gsub(command, "/all", ""));
        if message ~= "" then
            sendWorldMessage(message);
        end
        commandProcessed = true;
    elseif luautils.stringStarts(command, "/help") then
        ISChat.addLineInChat(nil, getListOfCommands(command), false, false);
        commandProcessed = true;
    elseif luautils.stringStarts(command, "/s ") or luautils.stringStarts(command, "/shout ") then
        isShout = true;
        if luautils.stringStarts(command, "/s ") then
            command = string.sub(command, #"/s ");
        elseif luautils.stringStarts(command, "/shout ") then
            command = string.sub(command, #"/shout ");
        end
    elseif luautils.stringStarts(command, "/w ") or luautils.stringStarts(command, "/whisper ") then
        isWhisper = true;
        if luautils.stringStarts(command, "/w ") then
            command = string.sub(command, #"/w ");
        elseif luautils.stringStarts(command, "/whisper ") then
            command = string.sub(command, #"/whisper ");
        end
    elseif luautils.stringStarts(command, "/") then
        SendCommandToServer(command);
        commandProcessed = true;
    end
    if not commandProcessed then
        local suffix = "";
        if isShout then
            getPlayer():SayShout(command);
            suffix = " (shout)";
        elseif isWhisper then
            getPlayer():SayWhisper(command);
            suffix = " (whisper)";
        else
            getPlayer():Say(command);
        end

        if getServerOptions():getBoolean("LogLocalChat") then
            command = string.gsub(command, "<", "&lt;")
            command = string.gsub(command, ">", "&gt;")
            ISChat.addLineInChat(getOnlineUsername() .. suffix, command, true, true);
        end
    end
    doKeyPress(false);
    ISChat.instance.timerTextEntry = 20;
end

function ISChat.onOtherKey(key)
--    print('key='..tostring(key)..' type='..type(key)..' KEY_ESCAPE='..tostring(Keyboard.KEY_ESCAPE)..' type='..type(Keyboard.KEY_ESCAPE))
    if key == Keyboard.KEY_ESCAPE then
        ISChat.instance.textEntry:clear();
        ISChat.instance.textEntry:unfocus();
        ISChat.instance.textEntry:setVisible(false);
    end
end

ISChat.addLineInChat = function(user, line, addLocal, addTimestamp)
     if luautils.stringStarts(line, "[SERVERMSG]") then
        ISChat.instance.servermsg = "SERVER : " .. line.sub(line, 12);
        ISChat.instance.servermsgTimer = 300;
        return;
     end
     if user and ISChat.instance.mutedUsers[user] then return end
     ISChat.instance.moreinfo:setVisible(true);
     ISChat.instance.chatText:setVisible(true);
     ISChat.invisibleTimer = ISChat.toggleInvisibleTimer;
     local chatText = ISChat.instance.chatText
     local vscroll = chatText.vscroll
     local scrolledToBottom = (chatText:getScrollHeight() <= chatText:getHeight()) or (vscroll and vscroll.pos == 1)
    if user then
        line = user.." : "..line
    end
     if addTimestamp then
        line =  "[" .. getHourMinute() .. "] " .. line;
     end
    if addLocal then
        line = getText("UI_chat_local") .. line
    end
    if #ISChat.lines > ISChat.maxLine then
       local newLines = {};
       for i,v in ipairs(ISChat.lines) do
           if i ~= 1 then
               table.insert(newLines, v);
           end
       end
       table.insert(newLines, line .. " <LINE> ");
       ISChat.lines = newLines;
    else
        table.insert(ISChat.lines, line .. " <LINE> ");
    end
     ISChat.instance.chatText.text = "";
    local newText = "";
    for i,v in ipairs(ISChat.lines) do
        if i == #ISChat.lines then v = string.gsub(v, " <LINE> $", "") end
        newText = newText .. v;
    end
     ISChat.instance.chatText.text = newText;
     ISChat.instance.chatText:paginate();
    if scrolledToBottom then
        ISChat.instance.chatText:setYScroll(-10000);
    end
end

ISChat.onToggleChatBox = function(key)
    -- T : local chat (not logged)
    if ISChat.instance==nil then return; end
    if key == getCore():getKey("Local Chat") then
        ISChat.instance.chatText:setVisible(true);
        ISChat.instance.textEntry:setVisible(true);
        ISChat.instance.textEntry:focus();
        ISChat.instance.textEntry:ignoreFirstInput();
        ISChat.instance.moreinfo:setVisible(true);
        ISChat.invisibleTimer = ISChat.toggleInvisibleTimer;
    end -- global chat (logged)
    if key == getCore():getKey("Global Chat") and getServerOptions():getBoolean("GlobalChat") then
        ISChat.instance.chatText:setVisible(true)
        ISChat.instance.textEntry:setVisible(true);
        ISChat.instance.textEntry:focus();
        ISChat.instance.textEntry:setText("/all ");
        ISChat.instance.textEntry:ignoreFirstInput();
        ISChat.instance.moreinfo:setVisible(true);
        ISChat.invisibleTimer = ISChat.toggleInvisibleTimer;
    end
end

ISChat.onKeyKeepPressed = function(key)
    if ISChat.instance==nil then return; end
    if key == 15 then -- if you keep pressed tab it show the global chat
        ISChat.instance.chatText:setVisible(true);
        ISChat.instance.moreinfo:setVisible(true);
        ISChat.invisibleTimer = 150;
    end
end

function ISChat:new (x, y, width, height)
    local o = {}
    --o.data = {}
    o = ISPanel:new(x, y, width, height);
    setmetatable(o, self)
    self.__index = self
    o.x = x;
    o.y = y;
    o.borderColor = {r=1, g=1, b=1, a=0.7};
    o.backgroundColor = {r=0, g=0, b=0, a=0.5};
    o.width = width;
    o.height = height;
    o.anchorLeft = true;
    o.anchorRight = false;
    o.anchorTop = true;
    o.anchorBottom = false;
    o.prevBtnTxt = getTexture("media/ui/sGuidePrevBtn.png");
    o.nextBtnTxt = getTexture("media/ui/sGuideNextBtn.png");
    o.closeBtnTxt = getTexture("media/ui/sGuideCloseBtn.png");
    o.background = false;
    o.timerTextEntry = 0;
    o.log = {};
    o.logIndex = 0;
    o.servermsg = "";
    o.servermsgTimer = 0;
    ISChat.instance = o;
    Events.OnTick.Add(ISChat.ontick);
    return o
end

ISChat.createChat = function()

    if not isClient() then
        return;
    end
--    ISChat.chat = ISChat:new(350,0,150,200);
    ISChat.chat = ISChat:new(0,0,1,1);
    ISChat.chat:initialise();
--    ISChat.chat:createChildren();
    ISChat.chat:addToUIManager();
    ISChat.chat:setVisible(true);
    ISChat.chat.moreinfo:bringToTop()
    if getServerOptions():getOption("ServerWelcomeMessage") ~= "" then
        ISChat.addLineInChat(nil, getServerOptions():getOption("ServerWelcomeMessage"), false, false);
    end
    ISChat.chat.chatText:paginate();
    ISLayoutManager.RegisterWindow('chat', ISCollapsableWindow, ISChat.chat.moreinfo)

    ISChat.instance.moreinfo:setVisible(true);
    ISChat.instance.chatText:setVisible(true);
    ISChat.invisibleTimer = ISChat.toggleInvisibleTimer;

    Events.OnWorldMessage.Add(ISChat.addLineInChat);
    Events.OnMouseDown.Add(ISChat.unfocus);
    Events.OnKeyPressed.Add(ISChat.onToggleChatBox);
    Events.OnKeyKeepPressed.Add(ISChat.onKeyKeepPressed);
end

-- RJ : Do this because of some delay your last key entered in chat can pop a "KeyPressed"
ISChat.ontick = function()
    if ISChat.instance and ISChat.instance.timerTextEntry > 0 then
        ISChat.instance.timerTextEntry = ISChat.instance.timerTextEntry - 1;
        if ISChat.instance.timerTextEntry == 0 then
            doKeyPress(true);
        end
    end
end

ISChat.unfocus = function()
    if ISChat.instance==nil then return;end

    ISChat.instance.textEntry:unfocus();
    ISChat.instance.textEntry:setVisible(false);
    ISChat.instance.textEntry:setText("");
end

function ISChat:onPressDown()
    ISChat.instance.logIndex = ISChat.instance.logIndex - 1;
    if ISChat.instance.logIndex < 0 then
        ISChat.instance.logIndex = 0;
    end
    if ISChat.instance.log and ISChat.instance.log[ISChat.instance.logIndex] then
        --        print(ISChat.instance.log[ISChat.instance.logIndex]);
        ISChat.instance.textEntry:setText(ISChat.instance.log[ISChat.instance.logIndex]);
    else
        ISChat.instance.textEntry:setText("");
    end
end

function ISChat:onPressUp()
    ISChat.instance.logIndex = ISChat.instance.logIndex + 1;
    if ISChat.instance.logIndex > #ISChat.instance.log then
        ISChat.instance.logIndex = #ISChat.instance.log;
    end
    if ISChat.instance.log and ISChat.instance.log[ISChat.instance.logIndex] then
        --        print(ISChat.instance.log[ISChat.instance.logIndex]);
        ISChat.instance.textEntry:setText(ISChat.instance.log[ISChat.instance.logIndex]);
    end
end

function ISChat:mute(username)
    if self.mutedUsers[username] then
        self.mutedUsers[username] = nil
    else
        self.mutedUsers[username] = true
    end
end

function ISChat:isMuted(username)
    return self.mutedUsers[username] ~= nil
end

Events.OnGameStart.Add(ISChat.createChat);

