local Event = require("gfx.event")
local Element = require("gfx.element")
local Padding = Element:new{
    left = 0,
    right = 0,
    top = 0,
    bottom = 0,
    element = nil
}

function Padding:_repositionElement()
  self.element:setPos(self:getPaddingLeft() + 1, self:getPaddingTop() + 1)
  self:resize{
    width = self:getWidth(),
    height = self:getHeight()
  }
end

function Padding:new(opts)
  local obj = Element.new(self, opts)
  obj:_repositionElement()
  obj.element:setParent(obj:_getWindow())
  return obj
end

function Padding:resize(opts)
  -- Un-pad dimensions and pass to child element
  return self.element:resize{
    width = (opts.width and opts.width - self:getPaddingLeft() - self:getPaddingRight()) or self:getWidth(),
    height = (opts.height and opts.height - self:getPaddingTop() - self:getPaddingBottom()) or self:getHeight()
  }
end

function Padding:draw()
  if Element.draw(self) then
    local win = self:_getWindow()
    win.clear()
    self.element:draw()
    return true
  end
  return false
end

function Padding:setDirty(fullInvalidate)
  Element.setDirty(self, fullInvalidate)
  if fullInvalidate then
    self.element:setDirty(fullInvalidate)
  end
end

function Padding:getPaddingLeft()
  return self.left or 0
end

function Padding:getPaddingRight()
  return self.right or 0
end

function Padding:getPaddingTop()
  return self.top or 0
end

function Padding:getPaddingBottom()
  return self.bottom or 0
end

local function compareSet(value, default, didChange)
  return value or default, didChange or (value ~= nil and value ~= default)
end

function Padding:setPadding(opts)
  if type(opts) ~= "table" then
    return
  end

  local changed = false
  self.left, changed = compareSet(opts.left, self.left, changed)
  self.right, changed = compareSet(opts.right, self.right, changed)
  self.top, changed = compareSet(opts.top, self.top, changed)
  self.bottom, changed = compareSet(opts.bottom, self.bottom, changed)

  if changed then
    self:_reload()
    self:_repositionElement()
  end
end

function Padding:getInnerWidth()
  return self.element:getWidth()
end

function Padding:getInnerHeight()
  return self.element:getHeight()
end

function Padding:getWidth()
  return self:getInnerWidth() + self:getPaddingLeft() + self:getPaddingRight()
end

function Padding:getHeight()
  return self:getInnerHeight() + self:getPaddingTop() + self:getPaddingBottom()
end

function Padding:findById(id)
  return Element.findById(self, id) or self.element:findById(id)
end

function Padding:handleEvent(evt)
  if Element.handleEvent(self, evt) then
    return true
  end

  local evtLocalCoords = Event.toElementLocalPosition(evt, self)
  if Event.isClickEvent(evt) then
    return Event.containsClick(self, evt) and self.element:handleEvent(evtLocalCoords)
  else
    return self.element:handleEvent(evtLocalCoords)
  end
end

function Padding:_reload()
  Element._reload(self)
  self.element:setParent(self:_getWindow())
end

function Padding:_isDirty()
  return Element._isDirty(self) or self.element:_isDirty()
end

return Padding