{-# LANGUAGE LambdaCase         #-}
{-# LANGUAGE GADTs              #-}
{-# LANGUAGE NamedFieldPuns     #-}
{-# LANGUAGE RankNTypes         #-}
{-# LANGUAGE StandaloneDeriving #-}

module GhcTags.CTag.Header
  ( Header (..)
  , HeaderType (..)
  , SomeHeaderType (..)
  -- * Utils
  , SingHeaderType (..)
  , headerTypeSing
  ) where

import           Data.Text (Text)


-- | A type safe representation of a /ctag/ header.
--
data Header where
    Header :: forall ty. Show ty =>
              { ()
headerType     :: HeaderType ty
              , Header -> Maybe Text
headerLanguage :: Maybe Text
              , ()
headerArg      :: ty
              , Header -> Text
headerComment  :: Text
              }
            -> Header

instance Eq Header where
    Header  { headerType :: ()
headerType = HeaderType ty
headerType0
            , headerLanguage :: Header -> Maybe Text
headerLanguage = Maybe Text
headerLanguage0
            , headerArg :: ()
headerArg  = ty
headerArg0
            , headerComment :: Header -> Text
headerComment = Text
headerComment0
            }
      == :: Header -> Header -> Bool
==
      Header { headerType :: ()
headerType = HeaderType ty
headerType1
             , headerLanguage :: Header -> Maybe Text
headerLanguage = Maybe Text
headerLanguage1
             , headerArg :: ()
headerArg  = ty
headerArg1
             , headerComment :: Header -> Text
headerComment = Text
headerComment1
             } =
        case (HeaderType ty
headerType0, HeaderType ty
headerType1) of
          (HeaderType ty
FileEncoding, HeaderType ty
FileEncoding) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
FileFormat, HeaderType ty
FileFormat) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
FileSorted, HeaderType ty
FileSorted) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
OutputMode, HeaderType ty
OutputMode) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
KindDescription, HeaderType ty
KindDescription) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
KindSeparator, HeaderType ty
KindSeparator) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
ProgramAuthor, HeaderType ty
ProgramAuthor) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
ProgramName, HeaderType ty
ProgramName) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
ProgramUrl, HeaderType ty
ProgramUrl) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
ProgramVersion, HeaderType ty
ProgramVersion) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
ExtraDescription, HeaderType ty
ExtraDescription) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty
FieldDescription, HeaderType ty
FieldDescription) ->
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (PseudoTag Text
name0, PseudoTag Text
name1) ->
            Text
name0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
name1 Bool -> Bool -> Bool
&&
            Maybe Text
headerLanguage0 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
headerLanguage1 Bool -> Bool -> Bool
&&
            ty
headerArg0 ty -> ty -> Bool
forall a. Eq a => a -> a -> Bool
== ty
ty
headerArg1 Bool -> Bool -> Bool
&&
            Text
headerComment0 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
headerComment1
          (HeaderType ty, HeaderType ty)
_ -> Bool
False

deriving instance Show Header

-- | Enumeration of header type and values of their corresponding argument
--
data HeaderType ty where
    FileEncoding      :: HeaderType Text
    FileFormat        :: HeaderType Int
    FileSorted        :: HeaderType Int
    OutputMode        :: HeaderType Text
    KindDescription   :: HeaderType Text
    KindSeparator     :: HeaderType Text
    ProgramAuthor     :: HeaderType Text
    ProgramName       :: HeaderType Text
    ProgramUrl        :: HeaderType Text
    ProgramVersion    :: HeaderType Text

    ExtraDescription  :: HeaderType Text
    FieldDescription  :: HeaderType Text
    PseudoTag         :: Text -> HeaderType Text

deriving instance Eq (HeaderType ty)
deriving instance Ord (HeaderType ty)
deriving instance Show (HeaderType ty)

-- | Existential wrapper.
--
data SomeHeaderType where
    SomeHeaderType :: forall ty. HeaderType ty -> SomeHeaderType


-- | Singletons which makes it easier to work with 'HeaderType'
--
data SingHeaderType ty where
    SingHeaderTypeText :: SingHeaderType Text
    SingHeaderTypeInt  :: SingHeaderType Int


headerTypeSing :: HeaderType ty -> SingHeaderType ty
headerTypeSing :: HeaderType ty -> SingHeaderType ty
headerTypeSing = \case
    HeaderType ty
FileEncoding     -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
FileFormat       -> SingHeaderType ty
SingHeaderType Int
SingHeaderTypeInt
    HeaderType ty
FileSorted       -> SingHeaderType ty
SingHeaderType Int
SingHeaderTypeInt
    HeaderType ty
OutputMode       -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
KindDescription  -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
KindSeparator    -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
ProgramAuthor    -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
ProgramName      -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
ProgramUrl       -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
ProgramVersion   -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText

    HeaderType ty
ExtraDescription -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    HeaderType ty
FieldDescription -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText
    PseudoTag {}     -> SingHeaderType ty
SingHeaderType Text
SingHeaderTypeText