local INVALID_FRAME = {
    WorldFrame = true,
    Hearthbag = true,
    TestHearthStone = true,
};

local dimensionX = 32
local dimensionY = 32
local bagParent = ContainerFrame1PortraitButton

local _dummy, core = ...; -- handles slash commands

-- item list
local defaultHearthstone = 6948
local defaultHearthstoneSpellID = 8690
local rubySlippers = 28585
local rubySlippersSpellID = 39937
local darkPortal = 184871
local darkPortalSpellID = 348699

-- our default savedvariables, if none exist yet. prevents nil error upon first ever addon login
HearthDB = HearthDB or {
	BAG = {
		["parent"] = "ContainerFrame1PortraitButton",
		["scale"] = 1,
		["position"] = {-3,2}
	},
	INHERIT = true,
	ITEM = defaultHearthstone,
	SPELLID = defaultHearthstoneSpellID,
};

-- adibags
-- this is the bag frame, but don't replace it. It's too small (maybe). Scaling with the bag frame seems to be fine with its settings.

local AdiBagsProfile = {
	["parent"] = "AdiBagsSimpleLayeredRegion1",
	["scale"] = 1.65,
	["position"] = {
		-25, -- [1]
		-6, -- [2]
	},
}


-- arkinventory
-- has the same menu for both left / right, so either can be used. scaling and resizing settings seem fine.

local ArkinventoryProfile = {
	["parent"] = "ARKINV_Frame1TitleActionButton0",
	["scale"] = 1.75,
	["position"] = {
		0, -- [1]
		0, -- [2]
	},
}


-- inventorian
-- requires special work on right / left click functionality. couldn't find resizing settings
local InventorianProfile = {
	["parent"] = "InventorianBagFrameIconButton",
	["scale"] = 2,
	["position"] = {
		0, -- [1]
		0, -- [2]
	},
}


-- baggins
-- left / right click should be fine - base frame has right click functionality but not the icon. thinner columns setting may break it

local BagginsProfile = {
	["parent"] = "BagginsBag1Section2",
	["scale"] = 1.1,
	["position"] = {
		-29, -- [1]
		50, -- [2]
	},
}

-- combuctor
-- both left nad right click are consumed, do not use portrait (this one is neat and has a lot of utility). Settings seem fine.

local CombuctorProfile = {
	["parent"] = "CombuctorInventoryFrame1",
	["scale"] = 1.45,
	["position"] = {
		-148, -- [1]
		113, -- [2]
	},
}

-- bagnon
-- anchored to the money frame because scaling and reshaping the frame breaks the addon.

local BagnonProfile = {
	["parent"] = "BagnonMoneyFrame1",
	["scale"] = 1.4,
	["position"] = {
		-213, -- [1]
		237, -- [2]
	},
}

-- baudbag
-- anchoring to the sfirst inventory slot itself because it scales best and is compatible with the background options.

local BaudbagProfile = {
	["parent"] = "BaudBagSubBag0Item1",
	["scale"] = 1.3,
	["position"] = {
		-10, -- [1]
		32, -- [2]
	},
}

-- sorted
-- very nice look / feel to it. Left click has settings functionality, will need to inherit it.
local SortedProfile = {
	["parent"] = "SortedFramePortraitButton",
	["scale"] = 1.85,
	["position"] = {
		-0, -- [1]
		-0, -- [2]
	},
}

-- elvUI
-- style doesn't fit very well, have to anchor to bag slot
local ElvuiProfile = {
		["parent"] = "ElvUI_ContainerFrameBag0Slot1",
		["scale"] = 2.5,
		["position"] = {
			-25, -- [1]
			14, -- [2]
		},
}

-- GW2 UI
-- style somewhat fits, anchoring to a bag button that may not exist on retail
local GW2Profile = {
	["parent"] = "MainMenuBarBackpackButton",
	["scale"] = 2,
	["position"] = {
		1, -- [1]
		50, -- [2]
	},
}

-- texture list
local hearthDefaultTex = "Interface/AddOns/Hearthbag/Hearthstone_Default.blp"
local hearthCooldownTex = "Interface/AddOns/Hearthbag/Hearthstone_Cooldown.blp"
local hearthCooldownBlip = "Interface/AddOns/Hearthbag/Hearthstone_Cooldown_blip.blp"
local hearthDesatTex = "Interface/AddOns/Hearthbag/Hearthstone_Desat.blp"
local hearthDownTex = "Interface/AddOns/Hearthbag/Hearthstone_Down.blp"
local hearthFrameHolder = "Interface/AddOns/Hearthbag/DropdownBackground.blp"
local hearthEndUpButton = "Interface/AddOns/Hearthbag/ArrowButton_HB.blp"
local hearthEndDownButton = "Interface/AddOns/Hearthbag/ArrowButton_HBDown.blp"
local hearthEndHighlight = "Interface/AddOns/Hearthbag/ArrowButton_HBHL.blp"
local hearthCheckUp = "Interface/AddOns/Hearthbag/CheckButton_Enabled.blp"
local hearthCheckDown = "Interface/AddOns/Hearthbag/CheckButton_Disabled.blp"
local hearthCheckOff = "Interface/AddOns/Hearthbag/CheckButton_Off.blp"

-- this is where hearthbag will jump to in combat
local combatFrame = CreateFrame("Frame", "CombatFrame", UIParent, nil);
combatFrame:SetMovable(true);
combatFrame:EnableMouse(true);
combatFrame:SetScript("OnMouseDown", function(self, button)
	if button == "LeftButton" and not self.isMoving then
		self:StartMoving();
		self.isMoving = true;
	end
end)
combatFrame:SetScript("OnMouseUp", function(self, button)
	if button == "LeftButton" and self.isMoving then
		self:StopMovingOrSizing();
		self.isMoving = false;
	end
end)
combatFrame:SetScript("OnHide", function(self)
	if ( self.isMoving ) then
		self:StopMovingOrSizing();
		self.isMoving = false;
	end
end)
combatFrame:SetPoint("CENTER", 0, 0);
combatFrame:SetSize(dimensionX,dimensionY);
combatFrame:SetClampedToScreen(true);
combatFrame:SetScale(HearthDB.BAG["scale"]*1.5);
local combatTex = combatFrame:CreateTexture("CombatTexture", "BACKGROUND");
combatTex:SetAllPoints(combatFrame);
combatTex:SetTexture(hearthDesatTex);
combatTex:SetAlpha(0.5);
combatFrame:Hide();




-- creates the first frame using a Secure Action Button Template
local hearthbag = CreateFrame("Button", "Hearthbag", ContainerFrame1PortraitButton, "SecureActionButtonTemplate");
hearthbag:SetSize((dimensionX*.85),(dimensionY*.85)); -- makes the size be proportional to the frame in case frame is scaled
hearthbag:SetPoint("CENTER", HearthDB.BAG["parent"], "CENTER", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
hearthbag:SetIgnoreParentScale(true)
local hearthbagTex = hearthbag:CreateTexture("HearthbagTex", "ARTWORK"); -- making the texture frame portion
hearthbagTex:SetAllPoints(true); -- auto-set our texture frame to all points established by Hearthbag

-- magical code stuff, basically will call upon the hearthstone item ID
local item = Item:CreateFromItemID(HearthDB.ITEM)
item:ContinueOnItemLoad(function()	-- this is friend. ensures the item is loaded with a mixin so you don't get item = nil	
	if UnitAffectingCombat("player") == false then
		hearthbag:RegisterForClicks("LeftButtonUp", "RightButtonUp");
		hearthbag:SetAttribute("*type1", "item");	-- set to "any left click," targets an item
		hearthbag:SetAttribute("item", item:GetItemName());	-- the targetted item is now using the Item:CreateFromItemID() from before
		--UpdateCheckInherit_OnClick()
	else
		core:Print("Cannot set button functions in combat!");
	end
end)

-- button that enables the panel the options populate on to
local scrollbackButton = CreateFrame("Button", "ScrollBackButton", hearthbag, nil);
scrollbackButton:SetSize(25, 25);
scrollbackButton:SetPoint("LEFT", -15, 0);
if scrollbackButton:GetFrameLevel() >= scrollbackButton:GetParent():GetFrameLevel() then
	scrollbackButton:SetFrameLevel(scrollbackButton:GetParent():GetFrameLevel() - 1);
end
scrollbackButton:SetNormalTexture(hearthEndUpButton);
scrollbackButton:SetPushedTexture(hearthEndDownButton);
scrollbackButton:SetHighlightTexture(hearthEndHighlight);


-- background frame for the options to parent to, but is also parented to the button and placed under it in strata
local scrollbackFrame = CreateFrame("Frame", "ScrollBackFrame", scrollbackButton, nil);
scrollbackFrame:SetSize(150, 35);
scrollbackFrame:SetPoint("CENTER", -45, 0);
if scrollbackFrame:GetFrameLevel() >= scrollbackFrame:GetParent():GetFrameLevel() then
	scrollbackFrame:SetFrameLevel(scrollbackFrame:GetParent():GetFrameLevel() - 1);
end
local scrollbackTex = scrollbackFrame:CreateTexture("ScrollBackTex", "BACKGROUND");
scrollbackTex:SetPoint("CENTER");
scrollbackTex:SetTexture(hearthFrameHolder);
scrollbackTex:SetDrawLayer("Background", 0);
scrollbackTex:SetAllPoints(scrollbackFrame);
scrollbackFrame:Hide();

-- the "end" button that can close the menu, works essentially the same as the background enabler button
local scrollbackendButton = CreateFrame("Button", "ScrollBackEndButton", scrollbackFrame, nil);
scrollbackendButton:SetSize(25, 25);
scrollbackendButton:SetPoint("LEFT", 10, 0);
if scrollbackendButton:GetFrameLevel() >= scrollbackendButton:GetParent():GetFrameLevel() then
	scrollbackendButton:SetFrameLevel(scrollbackendButton:GetParent():GetFrameLevel() - 1);
end

scrollbackendButton:SetNormalTexture(hearthEndUpButton);
scrollbackendButton:SetPushedTexture(hearthEndDownButton);
scrollbackendButton:SetHighlightTexture(hearthEndHighlight);

-- function that handles showing / hiding options panel
local function SBBTEX_ONCLICK()
	if scrollbackFrame:IsVisible() == true then
		scrollbackFrame:Hide();
	else
		scrollbackFrame:Show();
	end
end

local function smallbuttondown_ONMOUSEDOWN()
	PlaySoundFile("Interface\\AddOns\\Hearthbag\\Sounds\\TinyButtonDown.ogg", "SFX");
end

local function smallbuttonup_ONMOUSEUP()
	PlaySoundFile("Interface\\AddOns\\Hearthbag\\Sounds\\TinyButtonUp.ogg", "SFX");
end

scrollbackButton:SetScript("OnClick", SBBTEX_ONCLICK);
scrollbackendButton:SetScript("OnClick", SBBTEX_ONCLICK);
scrollbackButton:SetScript("OnMouseDown", smallbuttondown_ONMOUSEDOWN);
scrollbackendButton:SetScript("OnMouseDown", smallbuttondown_ONMOUSEDOWN);
scrollbackButton:SetScript("OnMouseUp", smallbuttonup_ONMOUSEUP);
scrollbackendButton:SetScript("OnMouseUp", smallbuttonup_ONMOUSEUP);

local checkboxbg = CreateFrame("Frame", "CheckBoxBG", scrollbackFrame, nil);
checkboxbg:SetSize(35, 35);
checkboxbg:SetPoint("CENTER", 0, 25);
local checkboxbgTex = checkboxbg:CreateTexture("ScrollBackTex", "BACKGROUND");
checkboxbgTex:SetTexture(hearthCheckDown);
checkboxbgTex:SetDrawLayer("Background", 0);
checkboxbgTex:SetAllPoints(checkboxbg);

-- frame that handles the true/false of inheriting addon right click frame
local InheritOptions = CreateFrame("CheckButton", "HearthAddons", checkboxbg);
InheritOptions:SetAllPoints(checkboxbg);
InheritOptions:SetPoint("CENTER", 0, 0);
InheritOptions:SetCheckedTexture(hearthCheckUp);
InheritOptions:SetDisabledCheckedTexture(hearthCheckOff);


-- handles what frame to "right click" per addon
local function UpdateCheckInherit_OnClick()
	if (HearthDB.INHERIT == true) then 
		if UnitAffectingCombat("player") == false then
			if (IsAddOnLoaded("Arkinventory") == true) then
				hearthbag:SetAttribute("*type2", "click");
				hearthbag:SetAttribute("clickbutton", ARKINV_Frame1TitleActionButton0);
			elseif (IsAddOnLoaded("Inventorian") == true) then
				hearthbag:SetAttribute("*type2", "macro");
				hearthbag:SetAttribute("macrotext", "/click InventorianBagFrameIconButton"); -- this is ugly and I hate it but it works and click / clickbutton / frame do not. I DON'T KNOW WHY. But this works.
			elseif (IsAddOnLoaded("Sorted") == true) then
				hearthbag:SetAttribute("*type2", "click");
				hearthbag:SetAttribute("clickbutton", SortedFramePortraitButton);
			else
				hearthbag:SetAttribute("*type1", "item");	-- set to "any left click," targets an item
				hearthbag:SetAttribute("item", item:GetItemName());	-- the targetted item is now using the Item:CreateFromItemID() from before
			end
		else
			core:Print("Cannot set button functions in combat!");
		end
	elseif (HearthDB.INHERIT == false) then
		if UnitAffectingCombat("player") == false then
			hearthbag:SetAttribute("*type2", nil);
		else
			core:Print("Cannot set button functions in combat!");
		end
	end
end

-- true/false of inheriting addon right click functions
local function CheckButtonUp_OnClick()
    if HearthDB.INHERIT == true then
        HearthDB.INHERIT = false
        InheritOptions:SetChecked(false)
        UpdateCheckInherit_OnClick();
    elseif HearthDB.INHERIT == false then
        HearthDB.INHERIT = true
        InheritOptions:SetChecked(true)
        UpdateCheckInherit_OnClick();
    end
    if HearthDB.INHERIT == nil then
        HearthDB.INHERIT = true
        UpdateCheckInherit_OnClick();
    end
end

-- grabs from savedvariables to make button "remember" what the user chose
local function CheckButtonStatus_OnShow()
    if HearthDB.INHERIT == true then
        InheritOptions:SetChecked(true);
    elseif HearthDB.INHERIT == false then
        InheritOptions:SetChecked(false);
    end
end

local function CheckButtonCombat_OnEvent()
	if UnitAffectingCombat("player") == true then
		InheritOptions:SetEnabled(false);
	else
		InheritOptions:SetEnabled(true);
	end
end

InheritOptions:RegisterEvent("PLAYER_REGEN_DISABLED");
InheritOptions:RegisterEvent("PLAYER_REGEN_ENABLED");
InheritOptions:SetScript("OnClick", CheckButtonUp_OnClick);
InheritOptions:SetScript("OnShow", CheckButtonStatus_OnShow);
InheritOptions:SetScript("OnEvent", CheckButtonCombat_OnEvent);



-- controls the behaviour of Hearthbag
local function hearthBag_OnMouseDown(self, button)	-- controls the mouse down behaviour, including the "down" texture
    local start, duration = GetSpellCooldown(HearthDB.SPELLID);
    local CastingHearth = select(8,UnitCastingInfo("player"));	-- I refuse to use == 1 for the item count because it may be possible to glitch the game and grab 2+ hearthstones
	if ((GetItemCount(HearthDB.ITEM) > 0) and (button == "LeftButton") and (duration == 0) and (CastingHearth ~= HearthDB.SPELLID) and (UnitOnTaxi("player") == false) and (IsPlayerMoving() == false) and (IsFalling() == false)) then
		hearthbagTex:SetTexture(hearthDownTex);
		PlaySoundFile("Interface\\AddOns\\Hearthbag\\Sounds\\ButtonDown" .. math.random(1, 4) ..  ".ogg", "SFX");	-- selects from a random number of sounds
	elseif (GetItemCount(HearthDB.ITEM) > 0) then	-- if the item exists but doesn't fullfil above criteria
		hearthbagTex:SetTexture(hearthDefaultTex);
	else									-- if the item does not exist or turns up nil
		hearthbagTex:SetTexture(hearthDesatTex);
	end
end
-- controls the mouse up behaviour, similar to mousedown function
local function hearthBag_OnMouseUp()
	local start, duration = GetSpellCooldown(HearthDB.SPELLID);
	local CastingHearth = select(8,UnitCastingInfo("player"));
	if (GetItemCount(HearthDB.ITEM) > 0) then
		hearthbagTex:SetTexture(hearthDefaultTex);
		if ((duration == 0) and (CastingHearth ~= HearthDB.SPELLID) and (UnitOnTaxi("player") == false) and (IsPlayerMoving() == false) and (IsFalling() == false)) then
			PlaySoundFile("Interface\\AddOns\\Hearthbag\\Sounds\\Button" .. math.random(1, 4) ..  ".ogg", "SFX");
		end
	else
		hearthbagTex:SetTexture(hearthDesatTex);
	end
end
-- this also sets the texture upon login
local function hearthDestroyed()
	if GetItemCount(HearthDB.ITEM) > 0 then
		hearthbagTex:SetTexture(hearthDefaultTex);
	else
		hearthbagTex:SetTexture(hearthDesatTex);
	end
end

hearthbag:SetScript("OnMouseDown", hearthBag_OnMouseDown);
hearthbag:SetScript("OnMouseUp", hearthBag_OnMouseUp);
--[[hearthbag:SetScript("OnEvent", function(self, event, arg1)
	if event == "ADDON_LOADED" and arg1 == AddonList then
		print("this is printing")
		hearthbag:SetPoint("TOPLEFT", HearthDB.BAG["parent"], "TOPLEFT", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetPoint("BOTTOMRIGHT", HearthDB.BAG["parent"], "BOTTOMRIGHT", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetParent(HearthDB.BAG["parent"])
	end
end);]]
hearthbag:SetScript("OnEvent", function(self, event)
	if event == "PLAYER_REGEN_DISABLED" then
		combatFrame:Show();
		hearthbag:ClearAllPoints();
		hearthbag:SetParent(combatFrame);
		--hearthbag:SetAllPoints(combatFrame);
		hearthbag:SetPoint("TOPLEFT", combatFrame, "TOPLEFT", 5, -5);
		hearthbag:SetPoint("BOTTOMRIGHT", combatFrame, "BOTTOMRIGHT", -5, 5);
		--hearthbag:SetPoint("BOTTOMRIGHT", combatFrame, "BOTTOMRIGHT", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetMovable(true);
		scrollbackButton:Hide();
	elseif event == "PLAYER_REGEN_ENABLED" then
		hearthbag:ClearAllPoints();
		hearthbag:SetPoint("CENTER", HearthDB.BAG["parent"], "CENTER", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetParent(HearthDB.BAG["parent"]);
		hearthbag:SetScale(HearthDB.BAG["scale"]);
		--hearthbag:SetPoint("BOTTOMRIGHT", HearthDB.BAG["parent"], "BOTTOMRIGHT", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		--hearthbag:SetSize((dimensionX*.85),(dimensionY*.85));
		--hearthbag:SetMovable(false);
		combatFrame:Hide();
		scrollbackButton:Show();
	end
end);

--hearthbag:RegisterEvent("PLAYER_LOGIN");
hearthbag:RegisterEvent("PLAYER_ENTERING_WORLD");
hearthbag:RegisterEvent("ADDON_LOADED");
hearthbag:RegisterEvent("PLAYER_REGEN_DISABLED");
hearthbag:RegisterEvent("PLAYER_REGEN_ENABLED");

-- the cooldown texture itself (the rune)
local hearthCD = CreateFrame("Cooldown", "HearthCD", Hearthbag, "CooldownFrameTemplate");
hearthCD:SetUseCircularEdge(true); -- makes the cooldown edge circular
hearthCD:SetSwipeTexture(hearthCooldownTex); -- set the cooldown texture to be the rune
hearthCD:SetSwipeColor(0.2,0.2,0.2,1.0); -- set the RGB of the rune to ~20% "brightness" (makes it dark)
hearthCD:SetDrawEdge(true); -- shows the blip on the CD
hearthCD:SetEdgeTexture(hearthCooldownBlip,1.0,1.0,1.0,1.0); -- makes the blip as bright as possible
hearthCD:SetRotation(-2.22); -- rotates the whole cooldown rune so that the tail end of the rune will fill out last. ~ -127 degrees

 -- checks the cooldown on the hearthstone spell portion of the item
local function hearthCheck()
    local start, duration = GetSpellCooldown(HearthDB.SPELLID);
    if duration ~= 0 then
        hearthCD:SetCooldown(start, duration);
    end
end

hearthCD:SetScript("OnEvent", hearthCheck);
hearthCD:HookScript("OnEvent", hearthDestroyed);

hearthCD:RegisterEvent("SPELL_UPDATE_COOLDOWN"); -- hearthstone effect is technically a spell
hearthCD:RegisterEvent("PLAYER_ENTERING_WORLD"); -- to ensure the cooldown is calculated upon login
hearthCD:RegisterEvent("BAG_UPDATE_COOLDOWN"); -- just in case spell doesn't do the thing
hearthCD:RegisterEvent("BAG_UPDATE"); -- this fires a lot

-- snapshots all frames at the current time of executing this function
local function CollectFrames()
	frames = {}
	local f
	while true do
		f = EnumerateFrames(f);
		if not f then break end
		if f.GetName and f:GetName() and f.IsVisible and f:IsVisible() and f.GetCenter and f:GetCenter() then
			tinsert(frames, f);
		end
	end	
end

local previewFrame = CreateFrame("Frame", "PreviewFrame", UIParent, nil);
previewFrame:SetSize(dimensionX, dimensionY);
previewFrame:SetPoint("CENTER", 0, 0);
previewFrame:SetScale(1);
previewFrame:SetFrameStrata("FULLSCREEN_DIALOG");
local previewFrameTex = previewFrame:CreateTexture("PreviewFrameTex", "BACKGROUND");
previewFrameTex:SetTexture(hearthDesatTex);
previewFrameTex:SetAllPoints(previewFrame);
previewFrame:Hide();

--the "yellow frame" placer similar to fstack
local function CreateButtonPlacer()
	local frame = CreateFrame("Frame", nil, UIParent)
	buttonPlacer = frame
	frame:EnableMouse(true);
	frame:EnableMouseWheel(true);
	frame:EnableKeyboard(true);
	frame:SetFrameStrata("FULLSCREEN_DIALOG");
	frame:SetAllPoints();
	frame:Hide();
	local targetMarker = frame:CreateTexture();
	targetMarker:SetColorTexture(1, 1, 0, .5);

	--local buttonPreview = CleanupButton(frame)
	previewFrame:EnableMouse(false);
	previewFrame:SetAlpha(.5);

	-- grabs info on the currently selected frame
	local function target(self)
		local f = frames[frame.index]
		frame.target = f
		local scale, x, y = f:GetEffectiveScale(), GetCursorPosition();
		targetMarker:SetAllPoints(f);
		--buttonPreview:SetScale(scale * self.scale);
		RaidNotice_Clear(RaidWarningFrame);
		RaidNotice_AddMessage(RaidWarningFrame, f:GetName(), ChatTypeInfo["SAY"]);
	end

	-- executes function to snapshot current frames
	frame:SetScript("OnShow", function(self)
		self.scale = 1
		self.index = 1
		CollectFrames();
		target(self);
		previewFrame:Show();
		previewFrame:SetScale(1);
	end)

	--press escape to cancel
	frame:SetScript("OnKeyDown", function(self, arg1)
		if arg1 == "ESCAPE" then
			self:Hide(); 
			previewFrame:Hide();
		end
	end)

	--mousewheel will cycle through frame selected
	frame:SetScript("OnMouseWheel", function(self, arg1)
		if IsControlKeyDown() then
			self.scale = max(0, self.scale + arg1 * .05);
			previewFrame:SetScale(self.target:GetEffectiveScale() * self.scale);
		else
			self.index = self.index + arg1
			if self.index < 1 then
				self.index = #frames
			elseif self.index > #frames then
				self.index = 1
			end
			target(self);
		end
	end)


	frame:SetScript("OnMouseDown", function(self)
		self:Hide();
		previewFrame:Hide();
		local x, y = GetCursorPosition();
		local targetScale, targetX, targetY = self.target:GetEffectiveScale(), self.target:GetCenter();
		
		-- for debugging
		--[[print("scale: " .. targetScale )
		print("GetCenter() X coord: " .. targetX )
		print("GetCenter() Y coord: " .. targetY )
		print("targetName: " .. self.target:GetName() )
		print("position X: " .. ((x/targetScale-targetX)/self.scale) )
		print("position Y: " .. ((y/targetScale-targetY)/self.scale) )
		print("highlighted frame scale: " .. self.scale )]]

		-- grabs the values stored and sets them as the SavedVars
		HearthDB.BAG = {parent=self.target:GetName(), position={(x/targetScale-targetX)/self.scale, (y/targetScale-targetY)/self.scale}, scale=self.scale}
		
		-- hearthbag should never be placed on WorldFrame or Hearhtbag (and child) frames itself, will change this later to the SavedVar setter
		if HearthDB.BAG["parent"] == ("WorldFrame" or "Hearthbag") then
			core:Print(HearthDB.BAG["parent"] .. " cannot be set as parent frame. Switching to UIParent instead.");
			HearthDB.BAG["parent"] = "UIParent"
		end
		--[[print("SV parent: " .. HearthDB.BAG["parent"])
		print("SV X position: " .. HearthDB.BAG["position"][1])
		print("SV Y position; " .. HearthDB.BAG["position"][2])
		print("SV scale: " .. HearthDB.BAG["scale"])]]
		
		-- updates the position to the newly set SavedVars
		hearthbag:SetPoint("CENTER", HearthDB.BAG["parent"], "CENTER", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		--hearthbag:SetPoint("CENTER", HearthDB.BAG["parent"], "CENTER", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetParent(HearthDB.BAG["parent"]);
		hearthbag:SetScale(HearthDB.BAG["scale"]);
	end)

	-- handles the position of the preview on the cursor using OnUpdate, currently unused for simplicity
	frame:SetScript("OnUpdate", function()
		local scale, x, y = previewFrame:GetEffectiveScale(), GetCursorPosition()
		previewFrame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x/scale, y/scale);
	end)
end

core.commands = {
	["reset"] = function()
		if UnitAffectingCombat("player") == false then
			--buttonResetter.key = 'BAG'
			--buttonResetter:Show()
			core:Print("Placement has been reset. Anchoring to: " .. HearthDB.BAG["parent"]);
			print("this command currently doesn't do anything.");
			--HearthDB.BAG = {parent="ContainerFrame1PortraitButton",scale=1,position={[1]=-3,[2]=2}}
			--UpdateButton(HearthDB.BAG)
		end
	end,

	["combat"] = function()
		if UnitAffectingCombat("player") == false then
			if combatFrame:IsVisible() == false then
				combatFrame:Show();
				core:Print("Now showing combat placement frame. Type '/hb combat' to disable the frame placer.")
			elseif combatFrame:IsVisible() == true then
				combatFrame:Hide();
			end
		else
			core:Print("You can't do that in combat!");
		end
	end,

	["placer"] = function()
		CreateButtonPlacer();
		buttonPlacer:Show();
	end,

	["help"] = function()
		core:Print("this is a temporary message for testing - type '/hb placer' to execute the frame selector. The preview frame won't show.")
		--core:Print("Type '/hearthbag' or '/hb' to place the button on a highlighted frame. Use ScrollWheel to cycle through the frames until you select the one of your choosing. Control+ScrollWheel will scale the size of the Hearthbag. '/hearthbag reset' will reset to a preset location, depending on your addons loaded.")
	end
};

local function HandleSlashCommands(str)
	if (#str == 0) and UnitAffectingCombat("player") == false then
		-- user entered "/hearthbag" or "/hb" with no additional args
		--buttonPlacer.key = 'BAG'
		--buttonPlacer:Show()
		core.commands.help();
		return;	
	elseif UnitAffectingCombat("player") == true then
		core:Print("You can't do that in combat!");
	end

	local args = {};
	for _dummy, arg in ipairs({ string.split(' ', str) }) do
		if (#arg > 0) then
			table.insert(args, arg);
		end
	end

	local path = core.commands; -- required for updating found table.

	for id, arg in ipairs(args) do

		if (#arg > 0) then --if string length is greater than 0
			arg = arg:lower();			
			if (path[arg]) then
				if (type(path[arg]) == "function") then				
					-- all remaining args passed to our function!
					path[arg](select(id + 1, unpack(args))); 
					return;					
				elseif (type(path[arg]) == "table") then				
					path = path[arg]; -- another sub-table found!
				end
			else
				core.commands.help();
				return;
			end
		end
	end
end

function core:Print(...)
    local prefix = string.format("|T" .. hearthDefaultTex .. ":14|t" .. "|ThearthDefaultTex|t" .. "|cff4fe6fcH|r|cff44e7ebe|r|cff4de7d6a|r|cff62e6bfr|r|cff7be4a6t|r|cff95e08eh|r|cffafdb78b|r|cffc9d466a|r|cffe2cb5ag|r:");	
    DEFAULT_CHAT_FRAME:AddMessage(string.join(" ", prefix, ...));
end

function core:init(event, name)
	if (name ~= "Hearthbag") then return end 

	SLASH_HEARTHBAG1 = "/hearthbag"
	SLASH_HEARTHBAG2 = "/hb"
	SlashCmdList.HEARTHBAG = HandleSlashCommands;
end

local events = CreateFrame("Frame");
events:RegisterEvent("ADDON_LOADED");
events:SetScript("OnEvent", core.init);

hearthbag:HookScript("OnEvent", function(self, event)
	if event == "PLAYER_ENTERING_WORLD" then
		hearthbag:SetPoint("CENTER", HearthDB.BAG["parent"], "CENTER", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		--hearthbag:SetPoint("BOTTOMRIGHT", HearthDB.BAG["parent"], "BOTTOMRIGHT", HearthDB.BAG["position"][1], HearthDB.BAG["position"][2]);
		hearthbag:SetParent(HearthDB.BAG["parent"]);
		hearthbag:SetScale(HearthDB.BAG["scale"])
		UpdateCheckInherit_OnClick();
	end
end);