-- assets/fonts :: the fonts object, which is a simple way to draw text with font.
-- Some of these functions are quite slow, so it's better to use them to generate
-- texture instead of text.

--[[
  Copyright © 2019 Kazhnuz

  Permission is hereby granted, free of charge, to any person obtaining a copy of
  this software and associated documentation files (the "Software"), to deal in
  the Software without restriction, including without limitation the rights to
  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  the Software, and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]

local Font = Object:extend()

-- Initilizing and configuring option

function Font:new(filename, size)
  local filename = filename
  self.font   = love.graphics.newFont(filename, size)
  self.filter = ""
  self:setColor(1, 1, 1, 1)
  self:setSpacing(false, 0)
  self.align  = "left"
end

function Font:set()
  love.graphics.setFont(self.font)
end

function Font:setColor(r, g, b, a)
  self.color = {}
  self.color.r = r
  self.color.g = g
  self.color.b = b
  self.color.a = a
end

function Font:setColorFromTable(color)
  self.color = color
end

function Font:setSpacing(use_custom, size)
  self.spacing = {}
  self.spacing.active = use_custom
  self.spacing.size   = size
end

function Font:setAlign(align)
  self.align = align
end

function Font:setFilter(filter)
  self.filter = filter
end

function Font:setLineHeight(height)
  self.font:setLineHeight(height)
end

-- get information functions

function Font:getHeight()
  local font = self.font
  return font:getHeight()
end

function Font:getWidth(string)
  local spacing = 0
  if (self.spacing.active == true) then
    local charNumber = string.len(string)
    spacing = self.spacing.size * charNumber
  end
  local width = self.font:getWidth(string) + spacing
  return width
end

function Font:getColor()
  return self.color
end

-- print functions

function Font:draw(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  -- draw text with color and effect applied
  local limit = limit or 0
  local align = align or self.align

  self:applyFilter(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  love.graphics.setColor(self.color.r, self.color.g, self.color.b, self.color.a)
  self:printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
end

function Font:print(text, x, y, align, r, sx, sy, ox, oy, kx, ky)

  self:set()
  if (self.spacing.active) then
    utils.graphics.printWithSpacing(text, self.spacing.size, align, x, y, r, sx, sy, ox, oy, kx, ky)
  else
    utils.graphics.print(text, align, x, y, r, sx, sy, ox, oy, kx, ky)
  end

end

function Font:printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:set()
  if (limit > 0) then
    love.graphics.printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  else
    self:print(text, x, y, align, r, sx, sy, ox, oy, kx, ky)
  end
end

-- FILTER SYSTEM

function Font:applyFilter(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  if self.filter == "shadow" then
    self:applyFilterShadow(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  elseif self.filter == "border" then
    self:applyFilterBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  elseif self.filter == "doubleborder" then
    self:applyFilterDoubleBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  end
end

function Font:applyFilterShadow(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  love.graphics.setColor(0, 0, 0, 1)
  self:printf(text, x+1, y+1, limit, align, align, r, sx, sy, ox, oy, kx, ky)
  utils.graphics.resetColor()
end

function Font:applyFilterBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  love.graphics.setColor(0, 0, 0, 1)

  self:printf(text, x-1, y-1, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x  , y-1, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x+1, y-1, limit, align, r, sx, sy, ox, oy, kx, ky)

  self:printf(text, x+1, y  , limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x-1, y  , limit, align, r, sx, sy, ox, oy, kx, ky)

  self:printf(text, x-1, y+1, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x  , y+1, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x+1, y+1, limit, align, r, sx, sy, ox, oy, kx, ky)

  utils.graphics.resetColor()
end

function Font:applyFilterDoubleBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky)
  love.graphics.setColor(0, 0, 0, 1)

  self:printf(text, x-2, y-2, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x  , y-2, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x+2, y-2, limit, align, r, sx, sy, ox, oy, kx, ky)

  self:printf(text, x+2, y  , limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x-2, y  , limit, align, r, sx, sy, ox, oy, kx, ky)

  self:printf(text, x-2, y+2, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x  , y+2, limit, align, r, sx, sy, ox, oy, kx, ky)
  self:printf(text, x+2, y+2, limit, align, r, sx, sy, ox, oy, kx, ky)

  utils.graphics.resetColor()
end

return Font
