


local function TempBG(obj)
	local f = obj:GetGui()
	f:SetBackdrop( { 
		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", 
		edgeFile = "edgeFile", tile = false, tileSize = 0, edgeSize = 32, 
		insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	local color = {r=0.4,g=0.5,b=0.6}
	if GHI_EffectColors then
		color = GHI_EffectColors[GHI_ColorList[random(1,6)]];
	end
	f:SetBackdropColor(color.r, color.g, color.b,1);
end

--===================================================
--										Text
--===================================================	

--[[	
******* API *******
	
Constructor
	font

Functions	
General
x		GetParent() g
x		SetParent(par)	g
Inherited from obj
x		Show()	obj
x		Hide()	obj
	
x		SetSelection(start[,end])	obj
x		GetSelection()	obj
		
x		GetLength()	obj
x		GetWidthPos(width)	obj
x		GetPosWidth(pos)	obj
		
x		SetOffset(x)	obj
x		GetOffset()	obj
x		GetHeight()	obj
x		GetWidth()	obj

x		GetGui()	obj
x		Dispose()	obj

x		Enable()
x		Disable()
x		IsEnabled()

Text only
x		GetFont()	text
x		SetFont(font)	text
x		GetText()	text
x		SetText(text)	text
x		InsertText(text)	text
x		SetReqNewline(newline)	text
x		GetReqNewline()	text
x		SetFocus(pos)	text
x		GetFocus()	text

******* Notes *******

Regarding Focus:
	The focus can be at position 0 to len-1. The only times it can be at pos = len 
	is when the text object is the last object on the line (in other words it does 
	not have any directly following text object)
	
Selection:
	Selection should be parsed down from Doc. E.g. line also got a SetSelection, 
	which indicates how much of the lines objects should be selected completely

--]]


local textDrag;
function GHU_Text(_parent) 
	local class = Class("GHU_Text","GHU_Object")
		
	local gui,parent;
	local font,text;
	
	local focusPos;
	local selectionStart,selectionEnd;
	local reqNewline;
	
	local enabled;
	
	-- local functions
	local function InvertColor(r,g,b,a)
		return {
			r = 1 - r,
			g = 1 - g,
			b = 1 - b,
		};
	end
	
	
	-- ***** functions *****
	-- show
	class.Show = function(self) 
		gui:Show();
		print("show",text);
	end
	class.Hide = function(self)
		-- remove selection
		self:SetSelection();
		self:SetFocus();
		
		gui:Hide();
		--gui.input:Hide();
		gui.marker:Hide();
		print("hide",text);
	end
	class.Dispose = function(self)
		self:Hide();
		--wipe(gui.input);
		wipe(gui.label);
		wipe(gui)
		wipe(self);
	end
	
	class.DeleteSelected = function(self)
		if selectionStart == 0 and selectionEnd == self:GetLength() then
			return true,"Text obj can be disabled. Everything is selected";		
		end
		local t= self:GetText();		
		self:SetText(t:sub(0,selectionStart)..t:sub(selectionEnd+1));
	end
	
	class.GetGui = function(self)
		return gui;
	end
	class.GetParent = function(self)
		return parent;
	end
	class.SetParent = function(self,par)
		parent = par;
	end
	
	class.GetOffset = function(self) 
		local _,_,_,x = gui:GetPoint(1);
		return x;	
	end
	class.SetOffset = function(self,xOff)
		gui:ClearAllPoints();
		local par = parent;
		if par.GetGui then
			par = par:GetGui();		
		end
		gui:SetPoint("BOTTOMLEFT",par,"BOTTOMLEFT",xOff,0);
	end
	
	-- get pos width
	class.GetPosWidth = function(self,pos)
		-- put input within boundries
		pos = max(0,min(pos,self:GetLength()));
		
		-- find the coordinate for the position
	
		gui.label:SetText(strsubutf8(text,0,pos));
		local x = gui.label:GetWidth();
		gui.label:SetText(text);
		return x;
	end
	class.GetWidthPos = function(self,width)
				
		local w = strlenutf8(text);
		local pos = w; --floor(w/2);
		local changer = pos;
		while true do
			changer = floor(changer/2 +0.5);
			gui.label:SetText(strsubutf8(text,0,pos) or "");
			
			local labelWidth = floor(gui.label:GetWidth());
			--print(labelWidth,">", floor(width+0.5),"changer",changer);
			if labelWidth == floor(width+0.5) then -- if the lenght is matching
				gui.label:SetText(text);	
				return pos;
			elseif labelWidth > width then
				pos = pos - changer;
			else
				pos = pos + changer;
			end
			if changer <= 1 then
				break;			
			end
			if pos > strlenutf8(text) then
				gui.label:SetText(text);	
				return strlenutf8(text)
			end
		end
		
		gui.label:SetText(text);	
		return pos;
	end
	class.GetLength = function(self)
		return strlenutf8(text or "");
	end
		
	-- font
	class.SetFont = function(self,_font,markedOnly) -- unit tested
		assert(type(_font)=="table" and _font.GetType and _font:GetType() == "GHU_Font","Useage: Text:SetFont(GHU_Font)");
				
		font = _font;
		
		local _,h = font:GetFont();
		gui:SetHeight(h);
		font:ApplyFont(gui.label);
		--gui.input:SetHeight(h);
		
		-- marker color
		gui.marker:SetHeight(h);
		local color = InvertColor(font:GetColor());
		gui.marker:SetBackdropColor(color.r,color.g,color.b,0.5);
		
	end
	class.GetFont = function(self)
		return font;
	end	
	
	class.GetHeight = function(self)
		local _,h = font:GetFont();
		return h;
	end
	class.GetWidth = function(self)
		return gui.label:GetWidth();		
	end
			
	class.SetText = function(self,_text)
		assert(type(_text)=="string","Text must be a string.");
		text = _text;
		gui.label:SetText(text);
		gui:SetWidth(gui.label:GetWidth()+3); 
		--print(gui:IsShown(),text);
	end
	class.GetText = function(self)
		return text;		
	end	
	class.InsertText = function(self,_text)
		assert(type(_text)=="string","Text must be a string.");
				
		-- insert text at the cursor position
		local p = focusPos or self:GetLength();
		local newText = text:sub(0,p).._text..text:sub(p+1);
		self:SetText(newText);						
	end
		
	--	focus
	class.SetFocus = function(self,pos)
		assert(type(pos)=="number" or pos == nil,"Focus position must be a number or nil");
		
		-- nil - Hide the Focus
		if not(pos) then 
			focusPos = pos;
			--gui.input:ClearFocus();	
			--gui.input:Hide();
			return 
		end
		
		-- save focusPos within boundries
		focusPos = max(0,min(pos,strlenutf8(text)));
			
		-- get width of position
		local x = self:GetPosWidth(focusPos)+self:GetOffset();
		
		--gui.input:SetPoint("TOPLEFT",gui,"TOPLEFT",x,0);
		--gui.input:SetText("");
		--gui.input:Show();
		--gui.input:SetFocus();
		return x,font;
	end
	class.GetFocusCoordinate = function(self)
		-- get width of position
		if not(focusPos) then return 0,font; end
		local x = self:GetPosWidth(focusPos)+self:GetOffset();
		return x,font;
	end
	class.GetFocus = function(self)
		return focusPos;	
	end
	
	-- Selection
	class.SetSelection = function(self,start,s_end)
		if type(start)=="table" then start = start[1]; end
		if type(s_end)=="table" then s_end = s_end[1]; end
			
		assert(type(start)=="number" or start == nil,"Illigal selection start. Number or nil, got "..type(start));
		assert(type(s_end)=="number" or s_end == nil,"Illigal selection start. Number or nil, got "..type(s_end));
		
		
		start = max(0,min(self:GetLength(),start or 0));
		s_end = max(0,min(self:GetLength(),s_end or self:GetLength()));
		
		assert(start <= s_end,"start pos larger than end pos",start,s_end);
		
		selectionStart = start;
		selectionEnd = s_end;
		
		-- if nothing marked		
		if (selectionStart == 0 and selectionEnd == 0) then
			gui.marker:Hide();
		end
		
		
		
		local xS = self:GetPosWidth(selectionStart);
		local xE = self:GetPosWidth(selectionEnd);		
	
		gui.marker:SetWidth(xE);
		gui.marker:SetPoint("TOPLEFT",gui,"TOPLEFT",xS,0);
		gui.marker:SetBackdropColor(1,1,1,1)
		
		gui.marker:Show();
	end
	class.GetSelection = function(self)
		return selectionStart,selectionEnd;
	end
	
	
	-- new line
	class.SetReqNewline = function(self,newLine)
		assert(type(newLine) == "boolean" or not(newLine),"Newline must be a boolean or nil");
		reqNewline = newLine;
	end
	class.GetReqNewline = function(self)
		return reqNewline;	
	end
	
	-- Enable
	class.Enable = function(self)
		enabled = true;
		self:Show();
	end
	class.Disable = function(self)
		enabled = false;	
		self:Hide();
	end
	class.IsEnabled = function(self)
		return enabled;	
	end
	
	-- ============== setup ==============
	-- gui (Button)
	selectionStart,selectionEnd = 0,0;
	focusPos = nil;
	text = "";
	reqNewline = false;
	enabled = true;
	parent = _parent;
	
	
	local f = parent;
	if (parent.GetGui) then 
		f = parent:GetGui();
	end
	
	gui = CreateFrame("Frame",nil,f);
	gui:ClearAllPoints();
	gui:SetPoint("BOTTOMLEFT",f,"BOTTOMLEFT",0,0);
	--gui:SetFrameLevel(100);
	--gui:SetFrameStrata("DIALOG");
	
	-- label to display the string
	gui.label = gui:CreateFontString()
	gui.label:ClearAllPoints();
	gui.label:SetPoint("TOPLEFT",gui,"TOPLEFT",0,0);
	
	gui:Hide();
	

	-- marker
	gui.marker = CreateFrame("Frame",gui);
	gui.marker:SetBackdrop( { 
		bgFile = "Interface\\CHATFRAME\\CHATFRAMEBACKGROUND", 
		edgeFile = "edgeFile", tile = false, tileSize = 0, edgeSize = 32, 
		insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	--
	gui.marker:SetBackdropColor(0,0,0,1);
	
	gui.marker:Hide();
	
	
	class:SetFont(GHU_Font());
	class:SetText("");
	
	GHU_TestBG(class);
	
	return class;
end
 
 