local ADDON_INFO = {
	name = "JoJoTrinkets",
	usage = {"/장신구","/trinket"},
};
ADDON_INFO.ver = GetAddOnMetadata(ADDON_INFO.name, 'Version')

BINDING_HEADER_JOJOTRINKETS = "어여쁜 장신구";
BINDING_NAME_JOJOTRINKET0 = "첫번째 장신구";
BINDING_NAME_JOJOTRINKET1 = "두번째 장신구";
---------------------------------------------------------------
local ICON_SIZE = 37;
local INSET = 10;
local MIN_RESIZE, MAX_RESIZE = 35, 150;
local MAX_NUM_TRINKETS = 36;

local INI = {
	arrange = "vertical",
	scale = 1,
	lock = false,
	tooltip = 1,
	shift = true,
};
-----------------------------------------------------------------------
-- Trinket List
local Trinkets = {};

local function ArrangeList(num)
	num = num>MAX_NUM_TRINKETS and MAX_NUM_TRINKETS or num;
	local K = ceil(num/6);
	local width, height;
	local inset = 5;
	local p, rt, rp, x, y;
	local arrange = JoJoTrinkets.config.arrange;
	for i=1,MAX_NUM_TRINKETS do
		local fn0 = "JoJoTrinketsButton";
		local fn = fn0..i;
		local f = getglobal(fn);
		
		if i<= num then
			f = f or CreateFrame("Button", fn, JoJoTrinketsListFrame, "JoJoTrinketsButtonTemplate");
			local c, r; 
			if arrange == "vertical" then
				c, r = ceil(i/K), mod(i,K);
				r = r==0 and K or r;
				p = r==1 and ( c==1 and "bottomleft" or "bottom" ) or "left";
				rt = r==1 and ( c==1 and "$parent" or fn0..(i-K) ) or fn0..(i-1);
				rp = r==1 and ( c==1 and "bottomleft" or "top" ) or "right";
				height = c; -- c when i==num
				width = K;
			else
				c, r = mod(i,K), ceil(i/K);
				c = c==0 and K or c;
				p = c==1 and ( r==1 and "bottomleft" or "left" ) or "bottom";
				rt = c==1 and ( r==1 and "$parent" or fn0..(i-K) ) or fn0..(i-1);
				rp = c==1 and ( r==1 and "bottomleft" or "right" ) or "top";
				height = K;
				width = r;
			end
			x = i==1 and inset or 0; 
			y = x;
			f:ClearAllPoints();
			f:SetPoint(p, rt, rp, x, y);
			f:Show();
		elseif f then
			f:Hide();
		end
	end
	
	width, height = ICON_SIZE*width+2*inset, ICON_SIZE*height+2*inset;
	JoJoTrinketsListFrame:SetSize(width, height);

	rt = "JoJoTrinketsFrame";
	local Cx, Cy = UIParent:GetCenter();
	local cx, cy = getglobal(rt):GetCenter();
	local up, right = cy > Cy, cx > Cx;
	
	if arrange == "vertical" then
		p = (up and "top" or "bottom") .. (right and "right" or "left");
		rp = (up and "top" or "bottom") .. (right and "left" or "right");
		x = right and 5 or -5;
		y = 0;
	else
		p = (up and "top" or "bottom") .. (right and "right" or "left");
		rp = (up and "bottom" or "top") .. (right and "right" or "left");
		x = 0;
		y = up and 5 or -5;
	end

	JoJoTrinketsListFrame:ClearAllPoints()
	JoJoTrinketsListFrame:SetPoint(p, rt, rp, x, y);
	JoJoTrinketsListFrame:Show();
end

local function SetListInfo()
	local index = 1;
	for itemLink, v in pairs(Trinkets) do
		local b = getglobal("JoJoTrinketsButton"..index);
		b.link, b.id = itemLink, v.id;
		b.bag, b.slot = v.bag, v.slot
		SetItemButtonTexture(b, v.texture);

		local cooldown = getglobal(b:GetName().."Cooldown");
		local start, duration, enable = GetItemCooldown(v.id);
		CooldownFrame_SetTimer(cooldown, start, duration, enable);

		index = index + 1;
	end
end

function JoJoTrinkets_UpdateList()
	wipe(Trinkets)
	local num = 0;
	local numSlots, equipLoc, texture
	
	for bag = 0, 4 do
		numSlots = GetContainerNumSlots(bag) or 0;
		for slot=1, numSlots do
			local itemLink = GetContainerItemLink(bag, slot);
			local id = GetContainerItemID(bag, slot)
			if itemLink then
				equipLoc, texture = select(9, GetItemInfo(GetContainerItemLink(bag,slot)))
				if equipLoc=="INVTYPE_TRINKET" then
					if not Trinkets[itemLink] then
						Trinkets[itemLink] = {texture=texture,id=id,bag=bag,slot=slot};
						num = num + 1
					end
				end
			end
		end
	end

	if num > 0 then
		num = num > MAX_NUM_TRINKETS and MAX_NUM_TRINKETS or num;
		JoJoTrinkets.numTrinkets = num;
		ArrangeList(num);
		SetListInfo();
	else
		JoJoTrinketsListFrame:Hide();
	end
end

function JoJoTrinkets_Swap(frame, slot)
	if InCombatLockdown() then
		JoJoTrinkets.waitingSwap = JoJoTrinkets.waitingSwap or {};

		local Waiting = JoJoTrinkets.waitingSwap;
		local link = frame.link;
		local button = "JoJoTrinket"..(slot-13).."Slot";
		local subTexture = getglobal(button.."SubTexture");
		local texture

		if not (Waiting[slot] and link==Waiting[slot]) then
			Waiting[slot] = link;
			texture = getglobal(frame:GetName().."IconTexture"):GetTexture();
			subTexture:SetTexture(texture);
			subTexture:Show();
		end
	else
		EquipItemByName(frame.link, slot);
	end
end

function JoJoTrinkets_UpdateListCooldown()
	--[[
	for i=1,MAX_NUM_TRINKETS do
		local name = "JoJoTrinketsButton"..i;
		local button = getglobal(name);
		local cooldown = getglobal(name.."Cooldown");

		if not button or not button.id or not button:IsVisible() then 
			if cooldown then cooldown:Hide() end
			return 
		else
			local start, duration, enable = GetItemCooldown(button.id);
			CooldownFrame_SetTimer(cooldown, start, duration, enable);
			cooldown:Show();
		end
	end]]
end
-----------------------------------------------------------------------
-- Slot Buttons
local function ButtonResize()
	local self = JoJoTrinkets;
	local arrange = self.config.arrange;
	local scale = self.config.scale;
	local w, h, p
	local size = ICON_SIZE*scale;
	local gap = 2

	if arrange == "vertical" then
		w, h = size+2*INSET, 2*size+2*INSET + gap;
	else
		w, h = 2*size+2*INSET + gap, size+2*INSET;
	end

	for i=0,1 do
		local b = getglobal("JoJoTrinket"..i.."Slot");
		local x,y
		if arrange == "vertical" then
			p = i==0 and "bottom" or "top";
			x = 0
			y = i==0 and gap/2 or -gap/2
		else
			p = i==0 and "right" or "left";
			x = i==0 and -gap/2 or gap/2
			y = 0
		end
		b:ClearAllPoints();
		b:SetPoint(p,"$parent","center",x,y);
		b:SetScale(scale);
	end
	local f, object = JoJoTrinketsFrame, JoJoTrinketsFrameBG;
	f:SetSize(w, h);
	object:SetSize(w-2*INSET, h-2*INSET);
end

local function UpdateButtonTexture()
	local Waiting = JoJoTrinkets.waitingSwap;

	for i=0,1 do
		local name = "JoJoTrinket"..i.."Slot";
		local button = getglobal(name);
		local texture = GetInventoryItemTexture("player", button:GetID());
		local subTexture = getglobal(name.."SubTexture");
		texture = texture or button.backgroundTextureName;
		SetItemButtonTexture(button, texture);
		if subTexture:IsVisible() then
			if texture==subTexture:GetTexture() then
				subTexture:Hide();
				Waiting[i+13] = nil;
			end
		end
	end
	if Waiting and not Waiting[13] and not Waiting[14] then
		Waiting = nil;
	end
end
local function UpdateButtonCooldown()
	for i=0,1 do
		local name = "JoJoTrinket"..i.."Slot";
		local button = getglobal(name);
		local cooldown = getglobal(name.."Cooldown");
		local start, duration, enable = GetInventoryItemCooldown("player", button:GetID());
		CooldownFrame_SetTimer(cooldown, start, duration, enable);
	end
end

-----------------------------------------------------------------------
-- config
local function Lock(state)
	local f = JoJoTrinketsFrame;
	local c = JoJoTrinketsFrameCorner;
	if state==1 then
		--f:EnableMouse(0)
		--f:SetMovable(0);
		c:Hide();
		f:SetBackdropBorderColor(1, 1, 1, 0);
		f.isLocked = 1;
		f:StopMovingOrSizing();
		f.isMoving = false;
	else
		f.isLocked = nil;
		--f:EnableMouse(1)
		--f:SetMovable(1);
		c:Show();
	end
	f.isLocked = state;
end

-----------------------------------------------------------------------
local function Print(msg, r, g, b)
	r , g , b = r or 1.0 , g or 1.0 , b or 1.0;
	DEFAULT_CHAT_FRAME:AddMessage(msg , r , g , b);
end

local function Notice(msg)
	Print(msg, 1,0.7,0.2);
end

local function HL(text)
	return format("|cFFFFFFFF%s|r",text);
end

local function Variables_Loaded(this)
	JoJoTrinkets_Saved = JoJoTrinkets_Saved or {};

	local Config = JoJoTrinkets_Saved
	if not Config.ver or floor(Config.ver*10)~=floor(ADDON_INFO.ver*10) then
		for param,v in pairs(INI) do
			Config[param] = v;
		end
		Config.ver = ADDON_INFO.ver;

		JoJoTrinketsFrame:ClearAllPoints();
		JoJoTrinketsFrame:SetPoint("Center","$parent");
		Notice(format("%s ver.%s Loaded. (%s)", ADDON_INFO.name, ADDON_INFO.ver, ADDON_INFO.usage[1]));
	end
	this.config = Config;

	ButtonResize()
	Lock(this.config.lock and 1 or 0)
end

local function Slahsh_Handler(msg)
	local self = JoJoTrinkets;
	local config = self.config;
	local msg = strupper(msg);

	Notice(format("-- 어여쁜 장신구 (%s ver.%s) --", ADDON_INFO.name, ADDON_INFO.ver));

	if msg == "RESET" or msg == "초기화" then
		if not InCombatLockdown() then
			wipe(config);
			for param,v in pairs(INI) do
				config[param] = v;
			end
			config.ver = ADDON_INFO.ver;

			ButtonResize();
			JoJoTrinketsFrame:ClearAllPoints();
			JoJoTrinketsFrame:SetPoint("Center","$parent");
			Lock(config.lock and 1 or 0);
			msg = "초기화 되었습니다.";
		else
			msg = "전투 중에는 불가능 합니다.";
		end
		Print(msg,1,1,0);

	elseif msg == "고정" or msg == "LOCK" then
		config.lock = not config.lock;
		msg = config.lock and "위치가 고정되었습니다." or "잠금이 해제되었습니다."
		Lock(config.lock and 1 or 0);
		Print(msg,1,1,0);
	elseif msg == "쉬프트" or msg == "SHIFT" then
		config.shift = not config.shift;
		msg = config.shift and "장신구목록을 Shift로 봅니다." or "장신구목록을 바로 봅니다."
		Print(msg,1,1,0);

	elseif msg == "툴팁" or msg == "TOOLTIP" then
		config.tooltip = config.tooltip + 1;
		config.tooltip = config.tooltip==3 and 0 or config.tooltip;

		if config.tooltip==1 then
			msg = "상세툴팁 보기";
		elseif self.config.tooltip==2 then
			msg = "간략툴팁 보기";
		else
			msg = "툴팁을 보지않습니다."
		end
		Print(msg,1,1,0);
	else
		Print(format("|cFF0096FF사용법|r: /장신구 [%s | %s | %s | %s]",
				HL("초기화"), HL("고정"), HL("쉬프트"), HL("툴팁") ),1,1,0);
		Print(format("  %s - 위치/크기 초기화",			HL("초기화(reset)")),1,1,0);
		Print(format("  %s - 위치 고정/해제",			HL("고정(lock)")),1,1,0);
		Print(format("  %s - 장신구목록 shift로 보기/바로보기",	HL("쉬프트(shift)")),1,1,0);
		Print(format("  %s - 툴팁 상세/간략/안보기",		HL("툴팁(tooltip)")),1,1,0);
		Print("|cFF0096FF좌클릭|r: 첫 번째 장신구에 착용");
		Print("|cFF0096FF우클릭|r: 두 번째 장신구에 착용");
	end
end
----------------------------------------------------------------------
function JoJoTrinkets_OnLoad(this)
	this.title = ADDON_INFO.name;
	this.version = ADDON_INFO.ver;
	
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UPDATE_BINDINGS");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("UNIT_INVENTORY_CHANGED");
	this:RegisterEvent("BAG_UPDATE_COOLDOWN");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("UNIT_SPELLCAST_STOP");
	
	SlashCmdList["JoJoTrinketsCOMMAND"] = Slahsh_Handler;
	SLASH_JoJoTrinketsCOMMAND1 = ADDON_INFO.usage[1];
	SLASH_JoJoTrinketsCOMMAND2 = ADDON_INFO.usage[2];
end

function JoJoTrinkets_OnEvent(this,event,arg1)
	if event == "UNIT_INVENTORY_CHANGED" and arg1=="player" then
		UpdateButtonTexture();
		UpdateButtonCooldown();
		if JoJoTrinketsListFrame:IsVisible() then
			JoJoTrinkets_UpdateList();
			JoJoTrinkets_UpdateListCooldown();
		end
		return
	elseif event == "BAG_UPDATE_COOLDOWN" then
		UpdateButtonCooldown();
		if JoJoTrinketsListFrame:IsVisible() then
			JoJoTrinkets_UpdateListCooldown();
		end
		return
	elseif event == "PLAYER_REGEN_ENABLED" or (event == "UNIT_SPELLCAST_STOP" and arg1=="player") then
		if this.waitingSwap then
			for slot,link in pairs(this.waitingSwap) do
				EquipItemByName(link, slot);
			end
		end
		return
	elseif event == "UPDATE_BINDINGS" then
		if not InCombatLockdown() then
			for i=0,1 do
				local key1, key2 = GetBindingKey("JOJOTRINKET"..i);
				local button = "JoJoTrinket"..i.."Slot";
				if key1 then SetOverrideBindingClick(this, false, key1, button); end
				if key2 then SetOverrideBindingClick(this, false, key2, button); end
			end
		end
		return
	end

	if event == "VARIABLES_LOADED" then
		this:UnregisterEvent(event)
		Variables_Loaded(this)
	elseif event == "PLAYER_ENTERING_WORLD" then
		this:UnregisterEvent(event)	
		UpdateButtonTexture();
		UpdateButtonCooldown();
	end
end
----------------------------
function JoJoTrinkets_Corner_OnMouseUp(button)
	local f = JoJoTrinketsResizingField;
	if not ( f.isSizing ) then return end
	f.isSizing = false;
	f:StopMovingOrSizing();
	f:Hide();
	if InCombatLockdown() then return end		

	local self = JoJoTrinkets;
	local arrange = self.config.arrange;
	local scale = self.config.scale;

	local w,h = f:GetSize();
	local arrange = w > h and "horizontal" or "vertical";
	local scale = (min(w,h)-2*INSET)/ICON_SIZE;
	self.config.arrange = arrange;
	self.config.scale = scale;
	ButtonResize();
end

function JoJoTrinkets_Corner_OnMouseDown(this,button)
	local f = JoJoTrinketsResizingField;
	if ( not f.isLocked ) or ( f.isLocked == 0 ) and button == "LeftButton" then
		f:SetMinResize(MIN_RESIZE, MIN_RESIZE);
		f:SetMaxResize(MAX_RESIZE, MAX_RESIZE);	
		f:ClearAllPoints();
		f:SetAllPoints(this:GetParent());
		f:StartSizing("BOTTOMRIGHT");
		f.isSizing = true;
		f:Show();
	end
end