local math = math

View = class("View")

function View:updateSize()
	self.width = self.current:getWidth()
	self.height = self.current:getHeight()
	self.left = self.current.l
	self.right = self.current.r
	self.top = self.current.t
	self.bottom = self.current.b
end

function View:new(left, top, right, bottom)
	local v = instance(self)
	v.visible = true
	v.current = Bounds:new(left or 0, top or 0, right or (window.w-1), bottom or (window.h-1))
	v.target = Bounds:copy(v.current)
	v.clip = Bounds:copy(v.current)
	v.scissor = true
	v:updateSize()
	
	return v
end

function View:setBounds(left, right, top, bottom)
	self.current:set(left, right, top, bottom)
	self.target:copyFrom(self.current)
	self:updateSize()
end

function View:setTargetBounds(left, right, top, bottom)
	self.target:set(left, right, top, bottom)
end

function View:getCenterX()
	return self.current:getCenterX()
end

function View:getCenterY()
	return self.current:getCenterY()
end

function View:xToCamera(x, camera)
	return (x - self.left - self.width*0.5)/camera.zoom
end

function View:yToCamera(y, camera)
	return (y - self.top - self.height*0.5)/camera.zoom
end

function View:setVisible(val)
	self.visible = val
end

function View:isVisible()
	return self.visible
end

function View:clampPosition(x,y,xpadding,ypadding)
	local xpadding = xpadding or 0
	local ypadding = ypadding or 0
	return math.min(self.current.r - math.min(xpadding,self.width/2), math.max(self.current.l + math.min(self.width/2,xpadding), x)), math.min(self.current.b - math.min(ypadding,self.height/2), math.max(self.current.t + math.min(self.height/2,ypadding), y))
end

function View:updateFade(time)
	if self.doFadeOut then
		if self.fadeOutTimer >= 1 and self.fadeOutCallback and self.fadeOutCallback.onComplete then
			self.fadeOutCallback.onComplete(self.fadeOutCallback)
		end
		if self.fadeOutTimer < 1 then
			self.fadeOutTimer = math.min(1,self.fadeOutTimer+time/0.5)
		end
	else
		if self.fadeOutTimer <= 0 and self.fadeInCallback and self.fadeInCallback.onComplete then
			self.fadeInCallback.onComplete(self.fadeInCallback)
		end
		if self.fadeOutTimer > 0 then
			self.fadeOutTimer = math.max(0,self.fadeOutTimer-time/2)
		end
	end
end

local morphSpeed = 1000
local factorMorphSpeed = 5

function View:update(time)
	if self.fadeOutTimer then
		self:updateFade(time)
	end
	
	if not self.current:matches(self.target) then
		self.current:approach(self.target, factorMorphSpeed*time, morphSpeed*time)
		self:updateSize()
	end
end

function View:fadeOut(callBack)
	self.doFadeOut = true
	self.fadeOutTimer = self.fadeOutTimer or 0
	self.fadeOutCallback = callBack
end

function View:fadeIn(callBack)
	self.doFadeOut = false
	self.fadeOutTimer = 1
	self.fadeInCallback = callBack
end

function View:disableScissor()
	self.scissor = false
end

function View:setScissorClip(left, top, right, bottom)
	self.clip:set(left or self.target.l, top or self.target.t , right or self.target.r, bottom or self.target.b)
end

function View:applyInsideScissorClip(left, top, right, bottom)
	video.setScissorClip(math.max(self.clip.l, left), math.max(self.clip.t, top), math.min(right, self.clip.r), math.min(bottom,self.clip.b))	
end

function View:applyScissorClip()
	video.setScissorClip(self.clip.l, self.clip.t, self.clip.r, self.clip.b)	
end

function View:restoreScissorClip()
	video.clearScissorClip()
end

function View:apply()
	if self.scissor then
		self:applyScissorClip()
	end
end


function View:restore()
	if self.scissor then
		self:restoreScissorClip()
	end
end

function View:render()
	video.renderSpriteRectangleOutline(self.left, self.top, self.right, self.bottom, 255, 255, 0, 0, nil,nil, 5)
	video.renderTextSprites(self.width, (self.left+self.right)*0.5, self.top + 20, 1, "small", 255,255,0,0)
	video.renderTextSprites(self.height, self.left+20, (self.top + self.bottom)*0.5 , 0, "small", 255,255,0,0)
end