Scrollbar = {}
Scrollbar_mt = { __index = Scrollbar }
setmetatable(Scrollbar, Control_mt)

function Scrollbar.Create(root, parentObject, onChange, isVertical, isHorizontal)
	-- Create object
	local scrollbar = Control.Create(root, parentObject)
	setmetatable(scrollbar, Scrollbar_mt)
	
	-- Set constants
	scrollbar.kMargin = 4
	scrollbar.kRoundedRectRadius = 5
	
	-- Set attributes
	scrollbar.onChange = onChange
	
	scrollbar.isVertical = isVertical
	scrollbar.isHorizontal = isHorizontal
	
	-- Create gradient
	scrollbar.gradient = GGradient()
	scrollbar.gradient:InsertColor(0, GColor(200, 200, 200))
	scrollbar.gradient:InsertColor(0.499, GColor(180, 180, 180))
	scrollbar.gradient:InsertColor(0.500, GColor(160, 160, 160))
	scrollbar.gradient:InsertColor(1, GColor(140, 140, 140))
	
	-- Create surfaces
	scrollbar.outlineSurface = nil
	scrollbar.activeSurface = nil
	
	-- Information that determines if we must recreate surface
	scrollbar.currentWidth = 0
	scrollbar.currentHeight = 0
	scrollbar.currentBarSize = 0
	
	-- These two variables are used for interaction with parent control
	scrollbar.barSize = 1
	scrollbar.pos = 0
	
	scrollbar.barSizeUnnormalized = nil
	
	return scrollbar
end

function Scrollbar:HandleEvent(window, rect, event, scrollPos)
	window:PushScissor(rect)
		local barOffset = 0
		local barRect = 0
		
		if (self.isVertical) then
			self.barSizeUnnormalized = (rect:GetHeight() - 2*self.kMargin) * self.barSize + 2*self.kMargin
			barOffset = rect.top + self.kMargin + (rect:GetHeight() - self.barSizeUnnormalized)*self.pos
			barRect = GRect(rect.left + self.kMargin, barOffset, rect.right - self.kMargin, barOffset + self.barSizeUnnormalized)
		elseif (self.isHorizontal) then
			self.barSizeUnnormalized = (rect:GetWidth() - 2*self.kMargin) * self.barSize + 2*self.kMargin
			barOffset = rect.left + self.kMargin + (rect:GetWidth() - self.barSizeUnnormalized)*self.pos
			barRect = GRect(barOffset, rect.top + self.kMargin, barOffset + self.barSizeUnnormalized, rect.bottom - self.kMargin)
		end
	
		-- Determine if point is inside
		self:SetHot((not self:IsOtherControlActive()) and barRect:IsPointInside(event.pos))
		
		if (self.isActive) then
			if (event.type==kGEventMouseMoved) then
				local topLeftPos = event.pos:Minus(self.dragStartOffset)
				
				if (self.isVertical) then
					self.pos = clamp((topLeftPos.y - rect.top - self.kMargin) / (rect:GetHeight() - 2*self.kMargin - self.barSizeUnnormalized), 0, 1)
				elseif (self.isHorizontal) then
					self.pos = clamp((topLeftPos.x - rect.left - self.kMargin) / (rect:GetWidth() - 2*self.kMargin - self.barSizeUnnormalized), 0, 1)
				end
				
				if self.onChange then
					self.onChange(self.pos)
				end

			elseif (event.type==kGEventMouseUp and event.button==kGEventMouseButtonLeft) then
				self:SetActive(false)
			end
		elseif (self.isHot) then
			if (event.type==kGEventMouseDown and event.button==kGEventMouseButtonLeft) then
				self:SetActive(true)
				self.dragStartOffset = event.pos:Minus(barRect:GetTopLeft())
			end
		end
	window:PopScissor()
end

function Scrollbar:Draw(window, rect)
	-- Check if we must update surfaces
	if (rect:GetWidth()~=self.currentWidth or rect:GetHeight()~=self.currentHeight or self.currentBarSize~=self.barSize) then
		-- Reset internal state parameters
		self.currentWidth = rect:GetWidth()
		self.currentHeight = rect:GetHeight()
		self.currentBarSize = self.barSize
		
		-- Create surfaces
		self.outlineSurface = GSurface(self.currentWidth, self.currentHeight)
		self.barSurface = GSurface(self.currentWidth, self.currentHeight)
		
		-- Draw surfaces
		-- .. outline surface
		local drawRect = GRect(0, 0, rect:GetWidth(), rect:GetHeight())
		drawRect:Offset(0.5, 0.5)
		self.outlineSurface:Clear(GColor(0, 0, 0, 0))
		
		local mustDraw = (self.isVertical and rect:GetHeight() > 2*self.kMargin) or
						 (self.isHorizontal and rect:GetWidth() > 2*self.kMargin)
		
		if (mustDraw) then
			self.outlineSurface:DrawRoundedRectOutlined(drawRect:CloneWithInset(self.kMargin), GColor(0, 0, 0), self.kRoundedRectRadius, 0.5)
		end
		
		self.outlineSurface:UpdateTexture()
		
		-- .. bar surface
		if (self.isVertical) then
			self.barSizeUnnormalized = (rect:GetHeight() - 2*self.kMargin) * self.barSize + 2*self.kMargin
			drawRect = GRect(0, 0, rect:GetWidth(), self.barSizeUnnormalized)
		elseif (self.isHorizontal) then
			self.barSizeUnnormalized = (rect:GetWidth() - 2*self.kMargin) * self.barSize + 2*self.kMargin
			drawRect = GRect(0, 0, self.barSizeUnnormalized, rect:GetHeight())
		end
		
		drawRect:Offset(0.5, 0.5)
		self.barSurface:Clear(GColor(0, 0, 0, 0))
		
		if (mustDraw) then
			if (self.isVertical) then
				self.barSurface:DrawRoundedRectHorizontalGradient(drawRect:CloneWithInset(self.kMargin + 0.5), self.gradient, self.kRoundedRectRadius - 1)
			elseif (self.isHorizontal) then
				self.barSurface:DrawRoundedRectVerticalGradient(drawRect:CloneWithInset(self.kMargin + 0.5), self.gradient, self.kRoundedRectRadius - 1)
			end
		end
		self.barSurface:UpdateTexture()
	end
	
	window:PushScissor(rect)
		self.outlineSurface:DrawTexture(rect:GetTopLeft())
		
		if (self.isVertical) then
			self.barSurface:DrawTexture(rect:GetTopLeft():Plus(0, self.pos * (rect:GetHeight() - self.barSizeUnnormalized)))
		elseif (self.isHorizontal) then
			self.barSurface:DrawTexture(rect:GetTopLeft():Plus(self.pos * (rect:GetWidth() - self.barSizeUnnormalized), 0))
		end
	window:PopScissor()
end
