{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration.TypeSynonym.Lhs
  ( TypeSynonymLhs
  , mkTypeSynonymLhs
  ) where

import qualified GHC.Types.Fixity as GHC
import HIndent.Ast.Name.Infix
import HIndent.Ast.Name.Prefix
import HIndent.Ast.NodeComments
import HIndent.Ast.Type.Variable
import HIndent.Ast.WithComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import {-# SOURCE #-} HIndent.Pretty
import HIndent.Pretty.Combinators
import HIndent.Pretty.NodeComments

data TypeSynonymLhs
  = Prefix
      { pName :: WithComments PrefixName -- Using `name` in both `Prefix` and `Infix` causes a type conflict.
      , typeVariables :: [WithComments TypeVariable]
      }
  | Infix
      { left :: WithComments TypeVariable
      , iName :: WithComments InfixName
      , right :: WithComments TypeVariable
      }

instance CommentExtraction TypeSynonymLhs where
  nodeComments Prefix {} = NodeComments [] [] []
  nodeComments Infix {} = NodeComments [] [] []

instance Pretty TypeSynonymLhs where
  pretty' Prefix {..} = spaced $ pretty pName : fmap pretty typeVariables
  pretty' Infix {..} = spaced [pretty left, pretty iName, pretty right]

mkTypeSynonymLhs :: GHC.TyClDecl GHC.GhcPs -> TypeSynonymLhs
mkTypeSynonymLhs GHC.SynDecl {tcdFixity = GHC.Prefix, ..} = Prefix {..}
  where
    pName = fromGenLocated $ fmap mkPrefixName tcdLName
    typeVariables =
      fmap mkTypeVariable . fromGenLocated <$> GHC.hsq_explicit tcdTyVars
mkTypeSynonymLhs GHC.SynDecl {tcdFixity = GHC.Infix, ..} =
  case GHC.hsq_explicit tcdTyVars of
    [l, r] -> Infix {..}
      where left = mkTypeVariable <$> fromGenLocated l
            iName = fromGenLocated $ fmap mkInfixName tcdLName
            right = mkTypeVariable <$> fromGenLocated r
    _ -> error "Unexpected number of type variables for infix type synonym."
mkTypeSynonymLhs _ = error "Not a type synonym."
