local capi = {screen=screen,client=client,mouse=mouse}
local wibox = require("wibox")
local awful = require("awful")
local cairo        = require( "lgi"              ).cairo
local color        = require( "gears.color"      )
local beautiful    = require( "beautiful"        )
local surface      = require( "gears.surface"    )
local layout       = require( "collision.layout" )
local util         = require( "collision.util"   )
local shape        = require( "gears.shape"      )
local shape        = require( "gears.shape"      )
local pango = require("lgi").Pango
local pangocairo = require("lgi").PangoCairo
local module = {}

local w = nil
local rad = 10
local border = 3

local function init()
  w = wibox{}
  w.ontop = true
  w.visible = true
end

local margin = 15

local function create_arrow(cr,x,y,width, height,direction)
  local r,g,b = util.get_rgb()
  cr:set_source_rgba(r,g,b,0.15)
  cr:set_antialias(1)

  local s = shape.transform(shape.arrow)
    : rotate_at(width/4, height/4, math.pi/2)

  if direction == 1 then
    s : rotate_at(width/4, height/4, math.pi)
  end

  s : translate(x, y)

  s(cr, width/2, height/2, nil)

  cr:fill()
end

local pango_l = nil
local function draw_shape(s,collection,current_idx,icon_f,y,text_height)
  local geo = capi.screen[s].geometry
  local wa  =capi.screen[s].workarea

  --Compute thumb dimensions
  local margins = 2*20 + (#collection-1)*20
  local width = (geo.width - margins) / #collection
  local ratio = geo.height/geo.width
  local height = width*ratio
  local dx = 20

  -- Do not let the thumb get too big
  if height > 150 then
    height = 150
    width = 150 * (1.0/ratio)
    dx = (wa.width-margins-(#collection*width))/2 + 20
  end

  -- Resize the wibox
  w.x,w.y,w.width,w.height = math.floor(geo.x),math.floor(y or (wa.y+wa.height) - margin - height),math.floor(geo.width),math.floor(height)

  local img = cairo.ImageSurface(cairo.Format.ARGB32, geo.width,geo.height)
  local img3 = cairo.ImageSurface(cairo.Format.ARGB32, geo.width,geo.height)
  local cr = cairo.Context(img)
  local cr3 = cairo.Context(img3)
  cr:set_source_rgba(0,0,0,0)
  cr:paint()

  -- Get the colors
  local white,bg = color("#FFFFFF"),color(beautiful.menu_bg_normal or beautiful.bg_normal)
  local nornal,focus = color(beautiful.fg_normal),color(beautiful.bg_urgent)

  -- Init the text properties
  if not pango_l then
    local pango_crx = pangocairo.font_map_get_default():create_context()
    pango_l = pango.Layout.new(pango_crx)
    pango_l:set_font_description(beautiful.get_font(font))
    pango_l:set_alignment("CENTER")
    pango_l:set_wrap("CHAR")
  end

  for k,v in ipairs(collection) do
    -- Shape bounding
    cr:set_source(white)

    local s = shape.transform(shape.rounded_rect) : translate(dx, 0)
    s(cr, width, height, 10)
    cr:fill()

    -- Borders and background
    cr3:set_source(k==current_idx and focus or nornal)
    util.draw_round_rect(cr3,dx+border,0+border,width-2*border,height-2*border,rad)

--     cr3:move_to(0,0)
--     s = shape.transform(shape.rounded_rect) : translate(dx+border, border)
--     s(cr3, width-2*border, height-2*border, rad)

    cr3:set_line_width(2*border + 4) -- The 4 is required to cover the non-antialiased region
    cr3:stroke_preserve()
    cr3:set_source(bg)
    cr3:fill()

    -- Print the icon
    local icon = icon_f(v,width-20,height-20-text_height)
    if icon then
      cr3:save()
      cr3:translate(dx+10,10)
      cr3:set_source_surface(icon)
      cr3:paint_with_alpha(0.7)
      cr3:restore()
    end

    -- Print a pretty line
    local r,g,b = util.get_rgb()
    cr3:set_source_rgba(r,g,b,0.7)
    cr3:set_line_width(1)
    cr3:move_to(dx+margin,height - text_height-border)
    cr3:line_to(dx+margin+width-2*margin,height - text_height-border)
    cr3:stroke()

    -- Pring the text
    pango_l.text = v.name
    pango_l.width = pango.units_from_double(width-16)
    pango_l.height = pango.units_from_double(height-text_height-10)
    cr3:move_to(dx+8,height-text_height-0)
    cr3:show_layout(pango_l)

    -- Draw an arrow
    if k == current_idx-1 then
      create_arrow(cr3,dx,0,width,height,1)
    elseif k == current_idx+1 then
      create_arrow(cr3,dx,0,width,height,nil)
    end

    dx = dx + width + 20
  end

  w:set_bg(cairo.Pattern.create_for_surface(img3))
  w.shape_bounding = img._native
  w.visible = true
end

function module.hide()
  w.visible = false
end

--Client related
local function client_icon(c,width,height)
  -- Get the content
  --TODO detect pure black frames
  local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height)
  local cr = cairo.Context(img)

  local geom = c:geometry()
  local scale = width/geom.width
  if geom.height*scale > height then
    scale = height/geom.height
  end
  local w,h = geom.width*scale,geom.height*scale

  -- Create a mask
  local s = shape.transform(shape.rounded_rect) : translate((width-w)/2, (height-h)/2)
  s(cr, w, h, 10)

  cr:clip()

  cr:translate((width-w)/2,(height-h)/2)

  -- Create a matrix to scale down the screenshot
  cr:save()
  cr:scale(scale,scale)

  -- Paint the screenshot in the rounded rectangle
  cr:set_source_surface(surface(c.content))

  cr:paint()
  cr:restore()

  -- Add icon on top, "solve" the black window issue
  local icon = surface(c.icon)

  if not icon then
    return img
  end

--   local w,h = icon:get_width(),icon:get_height()
--   local aspect,aspect_h = width / w,(height) / h
--   if aspect > aspect_h then aspect = aspect_h end
--   cr:translate((width-w*aspect)/2,(height-h*aspect)/2)
--   cr:scale(aspect, aspect)
--   cr:set_source_surface(icon)
--   cr:paint_with_alpha(0.5)

  return img
end

function module.display_clients(s,direction)
  if not w then
    init()
  end
  if direction then
    awful.client.focus.byidx(direction == "right" and 1 or -1)
    capi.client.focus:raise()
  end
  local clients = awful.client.tiled(s)
  local fk = awful.util.table.hasitem(clients,capi.client.focus)
  draw_shape(s,clients,fk,client_icon,nil,50)
end

function module.change_focus(mod,key,event,direction,is_swap,is_max)
  awful.client.focus.byidx(direction == "right" and 1 or -1)
  local c = capi.client.focus
  local s = c.screen
  c:raise()
  local clients = awful.client.tiled(s)
  local fk = awful.util.table.hasitem(clients,c)
  draw_shape(s,clients,fk,client_icon,nil,50)
  return true
end

--Tag related
local function tag_icon(t,width,height)
  local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height)
  local cr = cairo.Context(img)

  local has_layout = layout.draw(t,cr,width,height)

  -- Create a monochrome representation of the icon
  local icon_orig = surface(t.icon)
    if icon_orig then
      local icon = cairo.ImageSurface(cairo.Format.ARGB32, icon_orig:get_width(), icon_orig:get_height())
      local cr2 = cairo.Context(icon)
      cr2:set_source_surface(icon_orig)
      cr2:paint()

      cr2:set_source(color(beautiful.fg_normal))
      cr2:set_operator(cairo.Operator.IN)
      cr2:paint()

      local w,h = icon:get_width(),icon:get_height()
      local aspect,aspect_h = width / w,(height) / h
      if aspect > aspect_h then aspect = aspect_h end
      cr:translate((width-w*aspect)/2,(height-h*aspect)/2)
      cr:scale(aspect, aspect)
      cr:set_source_surface(icon)
      cr:paint_with_alpha(has_layout and 0.35 or 1)
    end
  return img
end

local function change_tag(s,direction,is_swap)
  local s = capi.client.focus and capi.client.focus.screen or capi.mouse.screen
  if not is_swap then
    awful.tag[direction == "left" and "viewprev" or "viewnext"](s)
  else
    -- Move the tag
    local t = capi.screen[s].selected_tag
    local cur_idx,count = awful.tag.getidx(t),#capi.screen[s].tags
    cur_idx = cur_idx + (direction == "left" and -1 or 1)
    cur_idx = cur_idx == 0 and count or cur_idx > count and 1 or cur_idx
    t.index = cur_idx
  end
  local tags = capi.screen[s].tags
  local fk = awful.util.table.hasitem(tags,capi.screen[s].selected_tag)
  draw_shape(s,tags,fk,tag_icon,capi.screen[s].workarea.y + 15,20)
end

function module.display_tags(s,direction,c,is_swap,is_max)
  if not w then
    init()
  end
  change_tag(s,direction,is_swap)
end

function module.change_tag(mod,key,event,direction,is_swap,is_max)
  change_tag(s,direction,is_swap)
  return true
end

return module
-- kate: space-indent on; indent-width 2; replace-tabs on;
