{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
{-# LANGUAGE KindSignatures, DataKinds, ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Pipeline.VertexInputState.SizeAlignment.Internal (
	SizeAlignmentList(sizeAlignmentList),
	SizeAlignmentListUntil(sizeAlignmentListUntil), MapSizableUntil,
	Size, Alignment, SizeAlignment ) where

import GHC.Generics
import Data.Kind
import Gpu.Vulkan.Pipeline.VertexInputState.GHC.Generics.TypeFam
import Gpu.Vulkan.Pipeline.VertexInputState.Data.Type.TypeFam
import Gpu.Vulkan.Pipeline.VertexInputState.Data.Type.TypeValMap

import Foreign.Storable.PeekPoke

type Size = Int
type Alignment = Int
type SizeAlignment = (Size, Alignment)

sizeAlignmentTypeList ::
	forall (as :: [Type]) . MapTypeVal2 Sizable as => [SizeAlignment]
sizeAlignmentTypeList :: forall (as :: [*]). MapTypeVal2 Sizable as => [SizeAlignment]
sizeAlignmentTypeList = forall (c :: * -> Constraint) (as :: [*]) b.
MapTypeVal2 c as =>
(forall a. c a => a -> b) -> [b]
mapTypeVal2 @Sizable @as (\(a
_ :: a) -> (forall a. Sizable a => Int
sizeOf' @a, forall a. Sizable a => Int
alignment' @a))

class SizeAlignmentList a where
	sizeAlignmentList :: [SizeAlignment]

	default sizeAlignmentList :: (
		MapTypeVal2 Sizable (Flatten (Rep a)) ) => [SizeAlignment]
	sizeAlignmentList = forall (as :: [*]). MapTypeVal2 Sizable as => [SizeAlignment]
sizeAlignmentTypeList @(Flatten (Rep a))

sizeAlignmentTypeMaybeList ::
	forall (mas :: Maybe [Type]) . MapTypeValMaybe2 Sizable mas =>
	Maybe [SizeAlignment]
sizeAlignmentTypeMaybeList :: forall (mas :: Maybe [*]).
MapTypeValMaybe2 Sizable mas =>
Maybe [SizeAlignment]
sizeAlignmentTypeMaybeList =
	forall (c :: * -> Constraint) (mas :: Maybe [*]) b.
MapTypeValMaybe2 c mas =>
(forall a. c a => a -> b) -> Maybe [b]
mapTypeValMaybe2 @Sizable @mas (\(a
_ :: a) -> (forall a. Sizable a => Int
sizeOf' @a, forall a. Sizable a => Int
alignment' @a))

class SizeAlignmentListUntil t a where
	sizeAlignmentListUntil :: Maybe [SizeAlignment]

	default sizeAlignmentListUntil :: (
		MapTypeValMaybe2 Sizable (Until t (Flatten (Rep a))) ) =>
		Maybe [SizeAlignment]
	sizeAlignmentListUntil =
		forall (mas :: Maybe [*]).
MapTypeValMaybe2 Sizable mas =>
Maybe [SizeAlignment]
sizeAlignmentTypeMaybeList @(Until t (Flatten (Rep a)))

type MapSizableUntil t ts = MapTypeValMaybe2 Sizable (Until t (Flatten (Rep ts)))