--[[

     Licensed under GNU General Public License v2
      * (c) 2014,      projektile
      * (c) 2013,      Luke Bonham
      * (c) 2010-2012, Peter Hofmann

--]]

local floor  = math.floor
local screen = screen

local cascade = {
    name     = "cascade",
    nmaster  = 0,
    offset_x = 32,
    offset_y = 8,
    tile     = {
        name          = "cascadetile",
        nmaster       = 0,
        ncol          = 0,
        mwfact        = 0,
        offset_x      = 5,
        offset_y      = 32,
        extra_padding = 0
    }
}

local function do_cascade(p, tiling)
    local t = p.tag or screen[p.screen].selected_tag
    local wa = p.workarea
    local cls = p.clients

    if #cls == 0 then return end

    if not tiling then
        -- Cascade windows.

        local num_c
        if cascade.nmaster > 0 then
            num_c = cascade.nmaster
        else
            num_c = t.master_count
        end

        -- Opening a new window will usually force all existing windows to
        -- get resized. This wastes a lot of CPU time. So let's set a lower
        -- bound to "how_many": This wastes a little screen space but you'll
        -- get a much better user experience.
        local how_many = (#cls >= num_c and #cls) or num_c

        local current_offset_x = cascade.offset_x * (how_many - 1)
        local current_offset_y = cascade.offset_y * (how_many - 1)

        -- Iterate.
        for i = 1,#cls,1 do
            local c = cls[i]
            local g = {}

            g.x      = wa.x + (how_many - i) * cascade.offset_x
            g.y      = wa.y + (i - 1) * cascade.offset_y
            g.width  = wa.width - current_offset_x
            g.height = wa.height - current_offset_y

            if g.width  < 1 then g.width  = 1 end
            if g.height < 1 then g.height = 1 end

            p.geometries[c] = g
        end
    else
        -- Layout with one fixed column meant for a master window. Its
        -- width is calculated according to mwfact. Other clients are
        -- cascaded or "tabbed" in a slave column on the right.

        --         (1)                 (2)                 (3)                 (4)
        --   +----------+---+    +----------+---+    +----------+---+    +----------+---+
        --   |          |   |    |          | 3 |    |          | 4 |    |         +---+|
        --   |          |   | -> |          |   | -> |         +---++ -> |        +---+|+
        --   |  1       | 2 |    |  1      +---++    |  1      | 3 ||    |  1    +---+|+|
        --   |          |   |    |         | 2 ||    |        +---++|    |      +---+|+ |
        --   |          |   |    |         |   ||    |        | 2 | |    |      | 2 |+  |
        --   +----------+---+    +---------+---++    +--------+---+-+    +------+---+---+

        local mwfact
        if cascade.tile.mwfact > 0 then
            mwfact = cascade.tile.mwfact
        else
            mwfact = t.master_width_factor
        end

        -- Make slave windows overlap main window? Do this if ncol is 1.
        local overlap_main
        if cascade.tile.ncol > 0 then
            overlap_main = cascade.tile.ncol
        else
            overlap_main = t.column_count
        end

        -- Minimum space for slave windows? See cascade.tile.lua.
        local num_c
        if cascade.tile.nmaster > 0 then
            num_c = cascade.tile.nmaster
        else
            num_c = t.master_count
        end

        local how_many = (#cls - 1 >= num_c and (#cls - 1)) or num_c

        local current_offset_x = cascade.tile.offset_x * (how_many - 1)
        local current_offset_y = cascade.tile.offset_y * (how_many - 1)

        if #cls <= 0 then return end

        -- Main column, fixed width and height.
        local c = cls[1]
        local g = {}
        -- Rounding is necessary to prevent the rendered size of slavewid
        -- from being 1 pixel off when the result is not an integer.
        local mainwid = floor(wa.width * mwfact)
        local slavewid = wa.width - mainwid

        if overlap_main == 1 then
            g.width = wa.width

            -- The size of the main window may be reduced a little bit.
            -- This allows you to see if there are any windows below the
            -- main window.
            -- This only makes sense, though, if the main window is
            -- overlapping everything else.
            g.width = g.width - cascade.tile.extra_padding
        else
            g.width = mainwid
        end

        g.height = wa.height
        g.x = wa.x
        g.y = wa.y

        if g.width < 1  then g.width  = 1 end
        if g.height < 1 then g.height = 1 end

        p.geometries[c] = g

        -- Remaining clients stacked in slave column, new ones on top.
        if #cls <= 1 then return end
        for i = 2,#cls do
            c = cls[i]
            g = {}

            g.width  = slavewid - current_offset_x
            g.height = wa.height - current_offset_y

            g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x
            g.y = wa.y + (i - 2) * cascade.tile.offset_y

            if g.width < 1  then g.width  = 1 end
            if g.height < 1 then g.height = 1 end

            p.geometries[c] = g
        end
    end
end

function cascade.tile.arrange(p)
    return do_cascade(p, true)
end

function cascade.arrange(p)
    return do_cascade(p, false)
end

return cascade
