local _G = getfenv(0);

-- Config
InfoPanel_Config = {};
local DefaultConfig = {
  showBorder = 1,
  alpha = 1,
  scale = 1,
  defaultTip = nil,
  attachChatFrame2 =nil,
  lock = nil,
  space = 2,
};

local lastPluginLeft,lastPluginRight;
InfoPanel_LeftPluginList = {};
InfoPanel_RightPluginList = {};

-- Init Specific Mod Vars
local f = CreateFrame("Frame","InfoPanelFrame",UIParent);
local modName = "InfoPanel";
local modVers = GetAddOnMetadata(modName,"Version");

--------------------------------------------------------------------------------------------------------
--                                           Misc Functions                                           --
--------------------------------------------------------------------------------------------------------

-- Standard OnLeave Function for Plugins
local function OnLeave()
  GameTooltip:Hide()
end

-- OnEnter
local function OnEnter(self)
  InfoPanel_MakeTip(self,"프레임 조정");
  GameTooltip:AddDoubleLine("Shift+LeftClick+드래그: 프레임 이동");
  GameTooltip:AddDoubleLine("좌측끝 Shift+RightClick+드래그: 프레임 좌측 크기 조정");
  GameTooltip:AddDoubleLine("우측끝 Shift+RightClick+드래그 : 프레임 우측 크기 조정");
  GameTooltip:AddDoubleLine("중앙상단 Shift+RightClick+드래그: 프레임 상단 크기 조정");
  GameTooltip:AddDoubleLine("중앙하단 Shift+RightClick+드래그 : 프레임 하단 크기 조정");
  GameTooltip:Show();
end

-- AdjustAnchors
local function AdjustAnchors(mode)
  -- InfoPanel
  f:SetClampedToScreen( true );
  -- ChatFrame2
  if InfoPanel_Config.attachChatFrame2 and (ChatFrame2:IsShown()) then
    f:ClearAllPoints();
    f:SetPoint("TOPLEFT",ChatFrame2,"BOTTOMLEFT",-2,-5);
    f:SetPoint("TOPRIGHT",ChatFrame2,"BOTTOMRIGHT",2,5);
  elseif mode == 0 then
    f:ClearAllPoints();
    f:SetPoint("CENTER",0,0);
  end
end

-- OnEvent
local function OnEvent(self,event)
  -- Set Default Config
  if (event == "VARIABLES_LOADED") then
    for name, value in pairs(DefaultConfig) do
      if (InfoPanel_Config[name] == nil) then
        InfoPanel_Config[name] = value;
      end
    end
    AdjustAnchors(0);
    f:SetScale(InfoPanel_Config.scale);
    f:SetBackdropColor(0.1,0.22,0.35,InfoPanel_Config.alpha);
    if InfoPanel_Config.showBorder then
      f:SetBackdropBorderColor(0.1,0.1,0.1,1);
    else
      f:SetBackdropBorderColor(0,0,0,0);
    end
  end
  if (event == "PLAYER_ENTERING_WORLD") then
    AdjustAnchors(1);
    InfoPanel_SetSpace();
  end
end

-- Setup the Main Frame
f:SetHeight(26);
f:SetWidth(370);
f:SetToplevel(1);
f:SetBackdrop({ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 8, edgeSize = 8, insets = { left = 2, right = 2, top = 2, bottom = 2 } });
f:SetBackdropColor(0.1,0.22,0.35,1);
f:SetBackdropBorderColor(0.1,0.1,0.1,1);
f:Show();
f:SetScript("OnEvent",OnEvent);
f:SetMovable(true);
f:SetResizable(true);
f:EnableMouse(true);
f:RegisterForDrag("LeftButton");
f:SetScript("OnDragStart",function()
  if InfoPanel_Config.lock then return end;
  if arg1 == "LeftButton" and IsShiftKeyDown() then
     this:StartMoving();
  end
end);
f:SetScript("OnDragStop",function()
  this:StopMovingOrSizing();
end);
f:SetScript("OnMouseDown", function(self,arg1)
  if InfoPanel_Config.lock then return end;
  if IsShiftKeyDown() and (arg1 == "RightButton") then
    if (MouseIsOver(self) and self:IsResizable()) then
      local cx, cy = GetCursorPosition();
      local scale = self:GetEffectiveScale();
    
      local left = self:GetLeft() * scale;
      local right = self:GetRight() * scale;
      local top = self:GetTop() * scale;
      local bottom = self:GetBottom() * scale;
    
      local phix = math.floor((right-left)/5); 
      local phiy = math.floor((top-bottom)/3); 
      if (cx < (left+phix))then
        self:StartSizing("LEFT");
        return;
      elseif (cx > (right-phix)) then
        self:StartSizing("RIGHT");
        return;
      elseif ( cy > (bottom+phiy) ) then
        self:StartSizing("TOP");
        return;
      elseif ( cy < (top-phiy) ) then
        self:StartSizing("BOTTOM");
        return;
      end
    end
  end
end)
f:SetScript("OnMouseUp", function(self)
  self:StopMovingOrSizing();
end)
f:SetScript("OnEnter",OnEnter);
f:SetScript("OnLeave",OnLeave);
f:RegisterEvent("VARIABLES_LOADED");
f:RegisterEvent("PLAYER_ENTERING_WORLD");
--------------------------------------------------------------------------------------------------------
--                                           Slash Handling                                           --
--------------------------------------------------------------------------------------------------------
_G["SLASH_"..modName.."1"] = "/ip";
SlashCmdList[modName] = function(cmd)
  -- Extract Paramters
  local param1, param2 = cmd:match("^([^%s]+)%s*(.*)$");
  param1 = (param1 and param1:lower() or cmd:lower());
  -- Show / Hide Frame
  if (param1 == "show") then
    if (f:IsVisible()) then
      f:Hide();
    else
      f:Show();
    end
  -- attach to ChatFrame2
  elseif (param1 == "attach") then
    InfoPanel_Config.attachChatFrame2 = not InfoPanel_Config.attachChatFrame2;
    AdjustAnchors(0);
    if InfoPanel_Config.attachChatFrame2 then
      AzMsg("InfoPanel-> 프레임위치가 2번 채팅창 하단으로 변경됨");
    else
      AzMsg("InfoPanel-> 프레임 위치가 화면 중앙으로 변경됨");
    end
  -- Show / Hide Border
  elseif (param1 == "border") then
    InfoPanel_Config.showBorder = not InfoPanel_Config.showBorder;
    if InfoPanel_Config.showBorder then
      f:SetBackdropBorderColor(0.1,0.1,0.1,1);
    else
      f:SetBackdropBorderColor(0.0, 0.0, 0.0, 0.0);
    end
  -- Set background alpha
  elseif (param1 == "alpha") then
    if tonumber(param2) then
      InfoPanel_Config.alpha = param2;
      f:SetBackdropColor(0.1,0.22,0.35,param2);
    else
      AzMsg("잘못된 투명도 값입니다.");
    end
  -- Set frame scale
  elseif (param1 == "scale") then
    if tonumber(param2) then
      InfoPanel_Config.scale = param2;
      f:SetScale(param2);
    else
      AzMsg("잘못된 스케일 값입니다.");
    end
  -- Show / Hide Tooltip
  elseif (param1 == "tip") then
    InfoPanel_Config.defaultTip = not InfoPanel_Config.defaultTip;
    if InfoPanel_Config.defaultTip then
      AzMsg("InfoPanel-> 툴팁 표시 상태로 변경됨");
    else
      AzMsg("InfoPanel-> 툴팁 숨김 상태로 변경됨");
    end
  -- Lock/Unlock
  elseif (param1 == "lock") then
    InfoPanel_Config.lock = not InfoPanel_Config.lock;
    if InfoPanel_Config.lock then
      AzMsg("InfoPanel-> 프레임 이동 및 크기변경 잠김 상태로 변경됨");
    else
      AzMsg("InfoPanel-> 프레임 이동 및 크기변경 가능 상태로 변경됨");
    end
  -- Invalid or No Command
  elseif (param1 == "space") then
    if tonumber(param2) then
      InfoPanel_Config.space = tonumber(param2);
      InfoPanel_SetSpace();
      AzMsg("InfoPanel-> 플러그인 표시 간격이 "..param2.." (으)로 변경되었습니다");
    else
      AzMsg("infoPanel-> 잘못된 값입니다.");
    end
  else
    UpdateAddOnMemoryUsage();
    AzMsg("----- |2"..modName.."|r |1"..modVers.."|r ----- |1"..format("%.2f",GetAddOnMemoryUsage(modName)).." |2kb|r -----");
    AzMsg(" |2명령어 사용법:|r ");
    AzMsg("/ip |2show|r = 프레임 보이기/숨기기");
    AzMsg("/ip |2attach|r = 프레임 위치 2번채팅창 하단/화면 중앙");
    AzMsg("/ip |2border|r = 테두리 보이기/숨기기");
    AzMsg("/ip |2alpha 값|r = 배경 투명도 변경");
    AzMsg("/ip |2scale 값|r = 프레임 스케일 변경");
    AzMsg("/ip |2tip|r = 툴팁 보이기/숨기기");
    AzMsg("/ip |2lock|r = 프레임 이동 및 크기 변경 잠금/해제");
    AzMsg("/ip |2space 값|r = 플러그인 표시 간격을 조정");
  end
end

--------------------------------------------------------------------------------------------------------
--                                Global Chat Message Function (Rev 3)                                --
--------------------------------------------------------------------------------------------------------
if (not AZMSG_REV or AZMSG_REV < 3) then
  AZMSG_REV = 3;
  function AzMsg(text)
    DEFAULT_CHAT_FRAME:AddMessage(tostring(text):gsub("|1","|cffffff80"):gsub("|2","|cffffffff"),128/255,192/255,255/255);
  end
end

--------------------------------------------------------------------------------------------------------
--                                       Plugin Helper Functions                                      --
--------------------------------------------------------------------------------------------------------

-- Add Plugin
function InfoPanel_AddPlugin(arg1)
  local frame = CreateFrame("Button",nil,f);
  frame:SetWidth(20);
  frame:SetHeight(f:GetHeight()-4);
  frame.icon = frame:CreateTexture(nil,"OVERLAY");
  frame.icon:SetPoint("LEFT",0,0);
  frame.icon:SetWidth(18);
  frame.icon:SetHeight(18);
  frame.text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight");
  frame.text:SetPoint("LEFT",frame.icon,"RIGHT",2,0);
  frame:SetScript("OnLeave",OnLeave);
  frame:EnableMouse(1);
  frame:RegisterForClicks("LeftButtonUp","RightButtonUp");
  frame:Show();
  
  -- Anchor
  if (arg1 == "right") then
    frame.isRightAligned = 1;
    if lastPluginRight then
    	frame:SetPoint("RIGHT",lastPluginRigth,"LEFT",2,0);
    else
    	frame:SetPoint("RIGHT",-10,0);
    end
  elseif (lastPluginLeft) then
    frame:SetPoint("LEFT",lastPluginLeft,"RIGHT",2,0);
  else
    frame:SetPoint("LEFT",10,0);
  end
  if frame.isRightAligned then 
  	table.insert(InfoPanel_RightPluginList,frame);
  	lastPluginRight = frame;
  else
  	table.insert(InfoPanel_LeftPluginList,frame);
  	lastPluginLeft = frame;
  end
  -- Return
  return frame;
end

-- Quick SetText for Plugins to use
function InfoPanel_SetText(f,text,...)
  local oldWidth = f.text:GetWidth();
  -- text
  if (select("#",...) > 0) then
    f.text:SetFormattedText(text,...);
  else
    f.text:SetText(text);
  end
  -- width
  if (abs(oldWidth - f.text:GetWidth()) > 3) then
    f:SetWidth(f.text:GetWidth() + f.icon:GetWidth() + 3);
  end
  -- tip
  if (GameTooltip:IsOwned(f)) and (f:GetScript("OnEnter")) then
    f:GetScript("OnEnter")(f);
  end
end

-- SetTextColor
function InfoPanel_SetTextColor(f,value,lowBoundry,highBoundry)
  if (value > highBoundry) then
    f.text:SetTextColor(0,1,0);
  elseif (value > lowBoundry) then
    f.text:SetTextColor(1,1,0);
  else
    f.text:SetTextColor(1,0,0);
  end
end

-- InitTip (Initializes the GTT for use)
function InfoPanel_MakeTip(frame,header,extra,...)
  -- Set Tip Anchor
  if (InfoPanel_Config.defaultTip) then
    GameTooltip_SetDefaultAnchor(GameTooltip,frame);
  elseif (frame.isRightAligned) then
    GameTooltip:SetOwner(frame,"ANCHOR_TOPRIGHT",4,0);
  else
    GameTooltip:SetOwner(frame,"ANCHOR_TOPLEFT");
  end
  -- Add Header
  if (not extra) then
    GameTooltip:AddLine(header,1,1,1);
  else
    GameTooltip:AddDoubleLine(header,extra,1,1,1,...);
  end
end

function InfoPanel_SetSpace()
	for k,v in ipairs(InfoPanel_LeftPluginList) do
		if k > 1 then
			v:SetPoint("LEFT",InfoPanel_LeftPluginList[k-1],"RIGHT",InfoPanel_Config.space,0);
		end
	end
	for k,v in ipairs(InfoPanel_RightPluginList) do
		if k > 1 then
			v:SetPoint("RIGHT",InfoPanel_RightPluginList[k-1],"LEFT",-InfoPanel_Config.space,0);
		end
	end
end
