module FFICXX.Generate.Type.Module where

import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..), Namespace(..) )
--
import FFICXX.Generate.Type.Cabal ( AddCInc, AddCSrc )
import FFICXX.Generate.Type.Class ( Class, TemplateClass, TopLevel )


-- | C++ side
--   HPkg is generated C++ headers by fficxx, CPkg is original C++ headers
data ClassImportHeader =
  ClassImportHeader {
    ClassImportHeader -> Class
cihClass :: Class
  , ClassImportHeader -> HeaderName
cihSelfHeader :: HeaderName -- ^ fficxx-side main header
  , ClassImportHeader -> [Namespace]
cihNamespace :: [Namespace]
  , ClassImportHeader -> String
cihSelfCpp :: String
  , ClassImportHeader -> [Either TemplateClass Class]
cihImportedClasses :: [Either TemplateClass Class]  -- ^ Dependencies TODO: clarify this.
  , ClassImportHeader -> [HeaderName]
cihIncludedHPkgHeadersInH   :: [HeaderName]         -- TODO: Explain why we need to have these two
  , ClassImportHeader -> [HeaderName]
cihIncludedHPkgHeadersInCPP :: [HeaderName]         --       separately.
  , ClassImportHeader -> [HeaderName]
cihIncludedCPkgHeaders      :: [HeaderName] -- ^ C++-side headers
  } deriving (Int -> ClassImportHeader -> ShowS
[ClassImportHeader] -> ShowS
ClassImportHeader -> String
(Int -> ClassImportHeader -> ShowS)
-> (ClassImportHeader -> String)
-> ([ClassImportHeader] -> ShowS)
-> Show ClassImportHeader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ClassImportHeader] -> ShowS
$cshowList :: [ClassImportHeader] -> ShowS
show :: ClassImportHeader -> String
$cshow :: ClassImportHeader -> String
showsPrec :: Int -> ClassImportHeader -> ShowS
$cshowsPrec :: Int -> ClassImportHeader -> ShowS
Show)


-------------------------
-- Haskell side module --
-------------------------

data ClassModule =
  ClassModule {
    ClassModule -> String
cmModule :: String
  , ClassModule -> ClassImportHeader
cmCIH :: ClassImportHeader
  , ClassModule -> [Either TemplateClass Class]
cmImportedModulesHighNonSource :: [Either TemplateClass Class]
    -- ^ imported modules that do not need source
    -- NOTE: source means the same cabal package.
    -- TODO: rename Source to something more clear.
  , ClassModule -> [Either TemplateClass Class]
cmImportedModulesRaw :: [Either TemplateClass Class]
    -- ^ imported modules for raw types.
  , ClassModule -> [Either TemplateClass Class]
cmImportedModulesHighSource :: [Either TemplateClass Class]
    -- ^ imported modules that need source
  , ClassModule -> [Either TemplateClass Class]
cmImportedModulesForFFI :: [Either TemplateClass Class]
  , ClassModule -> [String]
cmExtraImport :: [String]
  } deriving (Int -> ClassModule -> ShowS
[ClassModule] -> ShowS
ClassModule -> String
(Int -> ClassModule -> ShowS)
-> (ClassModule -> String)
-> ([ClassModule] -> ShowS)
-> Show ClassModule
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ClassModule] -> ShowS
$cshowList :: [ClassModule] -> ShowS
show :: ClassModule -> String
$cshow :: ClassModule -> String
showsPrec :: Int -> ClassModule -> ShowS
$cshowsPrec :: Int -> ClassModule -> ShowS
Show)


data TemplateClassModule =
  TCM {
    TemplateClassModule -> String
tcmModule :: String
  , TemplateClassModule -> TemplateClassImportHeader
tcmTCIH :: TemplateClassImportHeader
  } deriving (Int -> TemplateClassModule -> ShowS
[TemplateClassModule] -> ShowS
TemplateClassModule -> String
(Int -> TemplateClassModule -> ShowS)
-> (TemplateClassModule -> String)
-> ([TemplateClassModule] -> ShowS)
-> Show TemplateClassModule
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TemplateClassModule] -> ShowS
$cshowList :: [TemplateClassModule] -> ShowS
show :: TemplateClassModule -> String
$cshow :: TemplateClassModule -> String
showsPrec :: Int -> TemplateClassModule -> ShowS
$cshowsPrec :: Int -> TemplateClassModule -> ShowS
Show)


data TemplateClassImportHeader =
  TCIH {
    TemplateClassImportHeader -> TemplateClass
tcihTClass :: TemplateClass
  , TemplateClassImportHeader -> [HeaderName]
tcihCxxHeaders :: [HeaderName] -- ^ C++-side headers
  } deriving (Int -> TemplateClassImportHeader -> ShowS
[TemplateClassImportHeader] -> ShowS
TemplateClassImportHeader -> String
(Int -> TemplateClassImportHeader -> ShowS)
-> (TemplateClassImportHeader -> String)
-> ([TemplateClassImportHeader] -> ShowS)
-> Show TemplateClassImportHeader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TemplateClassImportHeader] -> ShowS
$cshowList :: [TemplateClassImportHeader] -> ShowS
show :: TemplateClassImportHeader -> String
$cshow :: TemplateClassImportHeader -> String
showsPrec :: Int -> TemplateClassImportHeader -> ShowS
$cshowsPrec :: Int -> TemplateClassImportHeader -> ShowS
Show)

data TopLevelImportHeader =
  TopLevelImportHeader {
    TopLevelImportHeader -> String
tihHeaderFileName    :: String
  , TopLevelImportHeader -> [ClassImportHeader]
tihClassDep          :: [ClassImportHeader]
  , TopLevelImportHeader -> [Either TemplateClass Class]
tihExtraClassDep     :: [Either TemplateClass Class]
    -- ^ Extra class dependencies outside current package.
    --   NOTE: we cannot fully construct ClassImportHeader for them.
  , TopLevelImportHeader -> [TopLevel]
tihFuncs             :: [TopLevel]
  , TopLevelImportHeader -> [Namespace]
tihNamespaces        :: [Namespace]
  , TopLevelImportHeader -> [HeaderName]
tihExtraHeadersInH   :: [HeaderName]
  , TopLevelImportHeader -> [HeaderName]
tihExtraHeadersInCPP :: [HeaderName]
  } deriving (Int -> TopLevelImportHeader -> ShowS
[TopLevelImportHeader] -> ShowS
TopLevelImportHeader -> String
(Int -> TopLevelImportHeader -> ShowS)
-> (TopLevelImportHeader -> String)
-> ([TopLevelImportHeader] -> ShowS)
-> Show TopLevelImportHeader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TopLevelImportHeader] -> ShowS
$cshowList :: [TopLevelImportHeader] -> ShowS
show :: TopLevelImportHeader -> String
$cshow :: TopLevelImportHeader -> String
showsPrec :: Int -> TopLevelImportHeader -> ShowS
$cshowsPrec :: Int -> TopLevelImportHeader -> ShowS
Show)

data PackageConfig =
  PkgConfig {
    PackageConfig -> [ClassModule]
pcfg_classModules :: [ClassModule]
  , PackageConfig -> [ClassImportHeader]
pcfg_classImportHeaders :: [ClassImportHeader]
  , PackageConfig -> TopLevelImportHeader
pcfg_topLevelImportHeader :: TopLevelImportHeader
  , PackageConfig -> [TemplateClassModule]
pcfg_templateClassModules :: [TemplateClassModule]
  , PackageConfig -> [TemplateClassImportHeader]
pcfg_templateClassImportHeaders :: [TemplateClassImportHeader]
  , PackageConfig -> [AddCInc]
pcfg_additional_c_incs :: [AddCInc]
  , PackageConfig -> [AddCSrc]
pcfg_additional_c_srcs :: [AddCSrc]
  }