{-# LANGUAGE NoMonomorphismRestriction #-}

module Types.Field
  ( Field(..)
  , FieldVal(..)
  , extensions
  , rexpModules
  , flibOptions
  , file
  , flibType
  , fieldName
  , spaces
  , commas
  , toolDepends
  , oldToolDepends
  , pcDepends
  , buildDeps
  , modules
  , module_
  , mixins_
  , desc
  , version
  , cabalVersion
  , longList
  , testedField
  , licenseField
  , spdxLicenseField
  , dependencies
  , nonEmpty
  , stringField
  , ffilter
  )
where

import           Distribution.Compiler
import           Distribution.License
import           Distribution.ModuleName
import qualified Distribution.SPDX             as SPDX
import           Distribution.Types.Dependency
import           Distribution.Types.ExeDependency
import           Distribution.Types.ForeignLibOption
import           Distribution.Types.ForeignLibType
import           Distribution.Types.LegacyExeDependency
import           Distribution.Types.Mixin
import           Distribution.Types.ModuleReexport
import           Distribution.Types.PkgconfigDependency
import           Distribution.Version
import           Documentation.Haddock.Parser
import           Documentation.Haddock.Types    ( DocH
                                                , _doc
                                                )
import           Language.Haskell.Extension
import           Prelude.Compat

data FieldVal
  = Dependencies [Dependency]
  | Version Version
  | CabalVersion (Either Version VersionRange)
  | License License
  | SPDXLicense SPDX.LicenseExpression
  | Str String
  | File String
  | Spaces [String]
  | Commas [String]
  | LongList [String]
  | Extensions [Extension]
  | Modules [ModuleName]
  | Module ModuleName
  | RexpModules [ModuleReexport]
  | TestedWith [(CompilerFlavor, VersionRange)]
  | ToolDepends [ExeDependency]
  | OldToolDepends [LegacyExeDependency]
  | PcDepends [PkgconfigDependency]
  | Mixins [Mixin]
  | FlibType ForeignLibType
  | FlibOptions [ForeignLibOption]
  deriving (Show)

data Field
  = Description (DocH () Identifier)
  | Field String
          FieldVal
  deriving (Show)

flibType n p = Just $ Field n (FlibType p)

flibOptions n p = Just $ Field n (FlibOptions p)

toolDepends n as = Just $ Field n (ToolDepends as)

oldToolDepends n as = Just $ Field n (OldToolDepends as)

pcDepends n as = Just $ Field n (PcDepends as)

rexpModules n as = Just $ Field n (RexpModules as)

mixins_ n as = Just $ Field n (Mixins as)

dependencies n as = Just $ Field n (Dependencies as)

licenseField n a = Just $ Field n (License a)

spdxLicenseField _ SPDX.NONE        = Nothing
spdxLicenseField n (SPDX.License a) = Just $ Field n (SPDXLicense a)

file n a = Just $ Field n (File a)

spaces n as = Just $ Field n (Spaces as)

commas n as = Just $ Field n (Commas as)

longList n as = Just $ Field n (LongList as)

extensions n as = Just $ Field n (Extensions as)

version n a = Just $ Field n (Version a)

cabalVersion _ (Right vr) | vr == anyVersion = Nothing
cabalVersion n a                             = Just $ Field n (CabalVersion a)

modules n as = Just $ Field n (Modules as)

module_ n a = Just $ Field n (Module a)

testedField n a = Just $ Field n (TestedWith a)

ffilter f g as | not (f as) = Nothing
               | otherwise  = g as

nonEmpty = ffilter (not . null)

fieldName (Field s _    ) = s
fieldName (Description _) = "description"

desc [] = Nothing
desc vs = Just (Description $ _doc $ parseParas Nothing vs)

buildDeps [] = Nothing
buildDeps vs = dependencies "build-depends" vs

stringField n p = Just (Field n (Str p))