module Render.Font.EvanwSdf.Model
  ( Model
  , VertexAttrs
  , InstanceAttrs(..)
  , vkInstanceAttrs
  , InstanceBuffer
  ) where

import RIO

import Foreign (Storable(..))
import Geomancy (Vec2, Vec4)
import Geomancy.Vec3 qualified as Vec3
import Vulkan.Core10 qualified as Vk
import Vulkan.NamedType ((:::))

import Resource.Buffer qualified as Buffer
import Resource.Model qualified as Model

type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs

type VertexAttrs = "uv" ::: Vec2

data InstanceAttrs = InstanceAttrs
  { vertRect     :: Vec4
  , fragRect     :: Vec4
  , color        :: Vec4
  , outlineColor :: Vec4

  , samplerId    :: Int32
  , textureId    :: Int32

  , smoothing    :: Float
  , outlineWidth :: Float
  }
  deriving (Eq, Show)

vkInstanceAttrs :: [Vk.Format]
vkInstanceAttrs =
  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset
  , Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset
  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Color
  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline color

  , Vk.FORMAT_R32G32_SINT         -- Sampler + texture IDs

  , Vk.FORMAT_R32G32_SFLOAT       -- Smoothing + outline width
  ]

instance Storable InstanceAttrs where
  alignment ~_ = 4
  sizeOf ~_ = 16 + 16 + 16 + 16 + 4 + 4 + 4 + 4

  peek ptr = do
    vertRect     <- peekByteOff ptr  0 -- +16
    fragRect     <- peekByteOff ptr 16 -- +16
    color        <- peekByteOff ptr 32 -- +16
    outlineColor <- peekByteOff ptr 48 -- +16
    samplerId    <- peekByteOff ptr 64 -- +4
    textureId    <- peekByteOff ptr 68 -- +4
    smoothing    <- peekByteOff ptr 72 -- +4
    outlineWidth <- peekByteOff ptr 76 -- +4
    pure InstanceAttrs{..}

  poke ptr InstanceAttrs{..} = do
    pokeByteOff ptr  0 vertRect
    pokeByteOff ptr 16 fragRect
    pokeByteOff ptr 32 color
    pokeByteOff ptr 48 outlineColor
    pokeByteOff ptr 64 samplerId
    pokeByteOff ptr 68 textureId
    pokeByteOff ptr 72 smoothing
    pokeByteOff ptr 76 outlineWidth

type InstanceBuffer stage = Buffer.Allocated stage InstanceAttrs
