local BBoxWidget = require("ui/widget/bboxwidget")
local Blitbuffer = require("ffi/blitbuffer")
local ButtonTable = require("ui/widget/buttontable")
local CenterContainer = require("ui/widget/container/centercontainer")
local Event = require("ui/event")
local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry")
local Math = require("optmath")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local VerticalGroup = require("ui/widget/verticalgroup")
local Device = require("device")
local Screen = Device.screen
local _ = require("gettext")

local ReaderCropping = WidgetContainer:extend{}

function ReaderCropping:onPageCrop(mode)
    self.ui:handleEvent(Event:new("CloseConfigMenu"))

    -- backup original zoom mode as cropping use "page" zoom mode
    self.orig_zoom_mode = self.view.zoom_mode
    if mode == "auto" then
        if self.document.configurable.text_wrap ~= 1 then
            self:setCropZoomMode(true)
        end
        return
    elseif mode == "none" then
        return
    end
    -- backup original view dimen
    self.orig_view_dimen = Geom:new{w = self.view.dimen.w, h = self.view.dimen.h}
    -- backup original view bgcolor
    self.orig_view_bgcolor = self.view.outer_page_color
    self.view.outer_page_color = Blitbuffer.COLOR_DARK_GRAY
    -- backup original footer visibility
    self.orig_view_footer_visibility = self.view.footer_visible
    self.view.footer_visible = false
    -- backup original page scroll
    self.orig_page_scroll = self.view.page_scroll
    self.view.page_scroll = false
    -- backup and disable original hinting state
    self.ui:handleEvent(Event:new("DisableHinting"))
    -- backup original reflow mode as cropping use non-reflow mode
    self.orig_reflow_mode = self.document.configurable.text_wrap
    if self.orig_reflow_mode == 1 then
        self.document.configurable.text_wrap = 0
        -- if we are in reflow mode, then we are already in page
        -- mode, just force readerview to recalculate visible_area
        self.view:recalculate()
    else
        self.ui:handleEvent(Event:new("SetZoomMode", "page"))
    end

    -- prepare bottom buttons so we know the size available for the page above it
    local button_table = ButtonTable:new{
        width = Screen:getWidth(),
        buttons = {{
            {
                text = _("Cancel"),
                callback = function() self:onCancelPageCrop() end,
            },
            {
                text = _("Apply crop"),
                callback = function() self:onConfirmPageCrop() end,
            },
        }},
        zero_sep = true,
        show_parent = self,
    }
    local button_container = FrameContainer:new{
        margin = 0,
        bordersize = 0,
        padding = 0,
        background = Blitbuffer.COLOR_WHITE,
        CenterContainer:new{
            dimen = Geom:new{
                w = Screen:getWidth(),
                h = button_table:getSize().h,
            },
            button_table,
        }
    }
    -- height available for page
    local page_container_h = Screen:getHeight()
    if Device:isTouchDevice() then
        -- non-touch devices do not need cancel and apply buttons
        page_container_h = page_container_h - button_table:getSize().h
    end
    local page_dimen = Geom:new{
        w = Screen:getWidth(),
        h = page_container_h,
    }
    -- resize document view to the available size
    self.ui:handleEvent(Event:new("SetDimensions", page_dimen))

    -- finalize crop dialog
    self.bbox_widget = BBoxWidget:new{
        ui = self.ui,
        view = self.view,
        document = self.document,
    }
    self.crop_dialog = VerticalGroup:new{
        align = "left",
        self.bbox_widget,
        (Device:isTouchDevice() and button_container) or nil, -- button bar only availble for touch devices
    }
    UIManager:show(self.crop_dialog)
    return true
end

function ReaderCropping:onConfirmPageCrop()
    --DEBUG("new bbox", new_bbox)
    UIManager:close(self.crop_dialog)
    local new_bbox = self.bbox_widget:getModifiedPageBBox()
    self.ui:handleEvent(Event:new("BBoxUpdate", new_bbox))
    local pageno = self.view.state.page
    self.document.bbox[pageno] = new_bbox
    self.document.bbox[Math.oddEven(pageno)] = new_bbox
    self:exitPageCrop(true)
    return true
end

function ReaderCropping:onCancelPageCrop()
    UIManager:close(self.crop_dialog)
    self:exitPageCrop(false)
    return true
end

function ReaderCropping:exitPageCrop(confirmed)
    -- restore hinting state
    self.ui:handleEvent(Event:new("RestoreHinting"))
    -- restore page scroll
    self.view.page_scroll = self.orig_page_scroll
    -- restore footer visibility
    self.view.footer_visible = self.orig_view_footer_visibility
    -- restore view bgcolor
    self.view.outer_page_color = self.orig_view_bgcolor
    -- restore reflow mode
    self.document.configurable.text_wrap = self.orig_reflow_mode
    -- restore view dimens
    self.ui:handleEvent(Event:new("RestoreDimensions", self.orig_view_dimen))
    self.view:recalculate()
    -- Exiting should have the same look and feel with entering.
    if self.orig_reflow_mode == 1 then
        self.ui:handleEvent(Event:new("RestoreZoomMode"))
    else
        self:setCropZoomMode(confirmed)
    end
end

function ReaderCropping:setCropZoomMode(confirmed)
    if confirmed then
        -- if original zoom mode is "page???", set zoom mode to "content???"
        local zoom_mode_type = self.orig_zoom_mode:match("page(.*)")
        self:setZoomMode(zoom_mode_type
                    and "content"..zoom_mode_type
                    or self.orig_zoom_mode)
        self.ui:handleEvent(Event:new("InitScrollPageStates"))
    else
        self:setZoomMode(self.orig_zoom_mode)
    end
end

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

function ReaderCropping:onReadSettings(config)
    if config:has("bbox") then
        self.document.bbox = config:readSetting("bbox")
    end
end

function ReaderCropping:onSaveSettings()
    self.ui.doc_settings:saveSetting("bbox", self.document.bbox)
end

return ReaderCropping
