local InputContainer = require("ui/widget/container/inputcontainer")
local Device = require("ui/device")
local Input = require("ui/input")
local Screen = require("ui/screen")
local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local Event = require("ui/event")
local DEBUG = require("dbg")
local _ = require("gettext")

local ReaderZooming = InputContainer:new{
	zoom = 1.0,
	-- default to nil so we can trigger ZoomModeUpdate events on start up
	zoom_mode = nil,
	DEFAULT_ZOOM_MODE = "page",
	current_page = 1,
	rotation = 0
}

function ReaderZooming:init()
	if Device:hasKeyboard() then
		self.key_events = {
			ZoomIn = {
				{ "Shift", Input.group.PgFwd },
				doc = _("zoom in"),
				event = "Zoom", args = "in"
			},
			ZoomOut = {
				{ "Shift", Input.group.PgBack },
				doc = _("zoom out"),
				event = "Zoom", args = "out"
			},
			ZoomToFitPage = {
				{ "A" },
				doc = _("zoom to fit page"),
				event = "SetZoomMode", args = "page"
			},
			ZoomToFitContent = {
				{ "Shift", "A" },
				doc = _("zoom to fit content"),
				event = "SetZoomMode", args = "content"
			},
			ZoomToFitPageWidth = {
				{ "S" },
				doc = _("zoom to fit page width"),
				event = "SetZoomMode", args = "pagewidth"
			},
			ZoomToFitContentWidth = {
				{ "Shift", "S" },
				doc = _("zoom to fit content width"),
				event = "SetZoomMode", args = "contentwidth"
			},
			ZoomToFitPageHeight = {
				{ "D" },
				doc = _("zoom to fit page height"),
				event = "SetZoomMode", args = "pageheight"
			},
			ZoomToFitContentHeight = {
				{ "Shift", "D" },
				doc = _("zoom to fit content height"),
				event = "SetZoomMode", args = "contentheight"
			},
		}
	end
	if Device:isTouchDevice() then
		self.ges_events = {
			Spread = {
				GestureRange:new{
					ges = "spread",
					range = Geom:new{
						x = 0, y = 0,
						w = Screen:getWidth(),
						h = Screen:getHeight(),
					}
				}
			},
			Pinch = {
				GestureRange:new{
					ges = "pinch",
					range = Geom:new{
						x = 0, y = 0,
						w = Screen:getWidth(),
						h = Screen:getHeight(),
					}
				}
			},
		}
	end
	self.ui.menu:registerToMainMenu(self)
end

function ReaderZooming:onReadSettings(config)
	-- @TODO config file from old code base uses globalzoom_mode
	-- instead of zoom_mode, we need to handle this imcompatibility
	-- 04.12 2012 (houqp)
	local zoom_mode = config:readSetting("zoom_mode")
	if not zoom_mode then
		zoom_mode = self.DEFAULT_ZOOM_MODE
	end
	self.ui:handleEvent(Event:new("SetZoomMode", zoom_mode))
end

function ReaderZooming:onCloseDocument()
	self.ui.doc_settings:saveSetting("zoom_mode", self.zoom_mode)
end

function ReaderZooming:onSpread(arg, ges)
	if ges.direction == "horizontal" then
		self:genSetZoomModeCallBack("contentwidth")()
	elseif ges.direction == "vertical" then
		self:genSetZoomModeCallBack("contentheight")()
	elseif ges.direction == "diagonal" then
		self:genSetZoomModeCallBack("content")()
	end
	return true
end

function ReaderZooming:onPinch(arg, ges)
	if ges.direction == "diagonal" then
		self:genSetZoomModeCallBack("page")()
	elseif ges.direction == "horizontal" then
		self:genSetZoomModeCallBack("pagewidth")()
	elseif ges.direction == "vertical" then
		self:genSetZoomModeCallBack("pageheight")()
	end
	return true
end

function ReaderZooming:onSetDimensions(dimensions)
	-- we were resized
	self.dimen = dimensions
	self:setZoom()
end

function ReaderZooming:onRestoreDimensions(dimensions)
	-- we were resized
	self.dimen = dimensions
	self:setZoom()
end

function ReaderZooming:onRotationUpdate(rotation)
	self.rotation = rotation
	self:setZoom()
end

function ReaderZooming:onZoom(direction)
	DEBUG("zoom", direction)
	if direction == "in" then
		self.zoom = self.zoom * 1.333333
	elseif direction == "out" then
		self.zoom = self.zoom * 0.75
	end
	DEBUG("zoom is now at", self.zoom)
	self:onSetZoomMode("free")
	self.view:onZoomUpdate(self.zoom)
	return true
end

function ReaderZooming:onSetZoomMode(new_mode)
	self.view.zoom_mode = new_mode
	if self.zoom_mode ~= new_mode then
		DEBUG("setting zoom mode to", new_mode)
		self.zoom_mode = new_mode
		self:setZoom()
		self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
	end
end

function ReaderZooming:onPageUpdate(new_page_no)
	self.current_page = new_page_no
	self:setZoom()
end

function ReaderZooming:onReZoom()
	self:setZoom()
	self.ui:handleEvent(Event:new("InitScrollPageStates"))
	return true
end

function ReaderZooming:getZoom(pageno)
	-- check if we're in bbox mode and work on bbox if that's the case
	local zoom = nil
	local page_size = {}
	if self.zoom_mode == "content"
	or self.zoom_mode == "contentwidth"
	or self.zoom_mode == "contentheight" then
		local ubbox_dimen = self.ui.document:getUsedBBoxDimensions(pageno, 1)
		--self.view:handleEvent(Event:new("BBoxUpdate", page_size))
		self.view:onBBoxUpdate(ubbox_dimen)
		page_size = ubbox_dimen
	else
		-- otherwise, operate on full page
		self.view:onBBoxUpdate(nil)
		page_size = self.ui.document:getNativePageDimensions(pageno)
		--page_size = self.ui.document:getPageDimensions(pageno, 1, 0)
	end
	-- calculate zoom value:
	local zoom_w = self.dimen.w / page_size.w
	local zoom_h = self.dimen.h / page_size.h
	if self.rotation % 180 ~= 0 then
		-- rotated by 90 or 270 degrees
		zoom_w = self.dimen.w / page_size.h
		zoom_h = self.dimen.h / page_size.w
	end
	if self.zoom_mode == "content" or self.zoom_mode == "page" then
		if zoom_w < zoom_h then
			zoom = zoom_w
		else
			zoom = zoom_h
		end
	elseif self.zoom_mode == "contentwidth" or self.zoom_mode == "pagewidth" then
		zoom = zoom_w
	elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then
		zoom = zoom_h
	end
	return zoom
end

function ReaderZooming:setZoom()
	-- nothing to do in free zoom mode
	if self.zoom_mode == "free" then
		return
	end
	if not self.dimen then
		self.dimen = self.ui.dimen
	end
	self.zoom = self:getZoom(self.current_page)
	self.ui:handleEvent(Event:new("ZoomUpdate", self.zoom))
end

function ReaderZooming:genSetZoomModeCallBack(mode)
	return function()
		self:setZoomMode(mode)
	end
end

function ReaderZooming:setZoomMode(mode)
	self.ui:handleEvent(Event:new("SetZoomMode", mode))
	self.ui:handleEvent(Event:new("InitScrollPageStates"))
end

function ReaderZooming:addToMainMenu(tab_item_table)
	if self.ui.document.info.has_pages then
		table.insert(tab_item_table.typeset, {
			text = _("Switch zoom mode"),
			sub_item_table = {
				{
					text = _("Zoom to fit content width"),
					callback = self:genSetZoomModeCallBack("contentwidth")
				},
				{
					text = _("Zoom to fit content height"),
					callback = self:genSetZoomModeCallBack("contentheight")
				},
				{
					text = _("Zoom to fit page width"),
					callback = self:genSetZoomModeCallBack("pagewidth")
				},
				{
					text = _("Zoom to fit page height"),
					callback = self:genSetZoomModeCallBack("pageheight")
				},
				{
					text = _("Zoom to fit content"),
					callback = self:genSetZoomModeCallBack("content")
				},
				{
					text = _("Zoom to fit page"),
					callback = self:genSetZoomModeCallBack("page")
				},
			}
		})
	end
end

return ReaderZooming
