{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE CPP                 #-}

-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

{-|
The module provides a higher level API over BodhiReleases
with a Release record type.
-}

module Distribution.Fedora.Release
  ( Release(..),
    getActiveReleases,
    getFedoraReleases,
    getEPELReleases,
    getBranchRelease
  )
where

import Control.Monad (guard)
import Data.Aeson(Object)
import Data.Maybe (mapMaybe)
import Distribution.Fedora.BodhiReleases

-- | Fedora Release data
data Release = Release {
    Release -> String
releaseName :: String,
    Release -> String
releaseVersion :: String,
    Release -> String
releaseIdPrefix :: String,
    Release -> String
releaseBranch :: String,
    Release -> Bool
releaseComposed :: Bool,
    Release -> String
releaseCandidateTag :: String,
    Release -> String
releaseDistTag :: String,
    Release -> Maybe String
releaseSettingStatus :: Maybe String,
    Release -> String
releaseState :: String,
    Release -> Bool
releaseAutomaticUpdates :: Bool,
    Release -> Maybe String
releaseTestingRepo :: Maybe String,
    Release -> String
releaseTestingTag :: String
  } deriving (Int -> Release -> ShowS
[Release] -> ShowS
Release -> String
(Int -> Release -> ShowS)
-> (Release -> String) -> ([Release] -> ShowS) -> Show Release
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Release -> ShowS
showsPrec :: Int -> Release -> ShowS
$cshow :: Release -> String
show :: Release -> String
$cshowList :: [Release] -> ShowS
showList :: [Release] -> ShowS
Show,Release -> Release -> Bool
(Release -> Release -> Bool)
-> (Release -> Release -> Bool) -> Eq Release
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Release -> Release -> Bool
== :: Release -> Release -> Bool
$c/= :: Release -> Release -> Bool
/= :: Release -> Release -> Bool
Eq)

readRelease :: Object -> Maybe Release
readRelease :: Object -> Maybe Release
readRelease Object
obj = do
  String
name <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"name" Object
obj
  String
ver <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"version" Object
obj
  String
idPref <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"id_prefix" Object
obj
  Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (String
idPref String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String
"FEDORA-CONTAINER",String
"FEDORA-FLATPAK"])
  String
br <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"branch" Object
obj
  Bool
composed <- Text -> Object -> Maybe Bool
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"composed_by_bodhi" Object
obj
  String
candidate <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"candidate_tag" Object
obj
  String
disttag <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"dist_tag" Object
obj
  let setting :: Maybe String
setting = Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"setting_status" Object
obj
  String
state <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"state" Object
obj
  Bool
automatic <- Text -> Object -> Maybe Bool
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"create_automatic_updates" Object
obj
  let testrepo :: Maybe String
testrepo = Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"testing_repository" Object
obj
  String
testtag <- Text -> Object -> Maybe String
forall a. FromJSON a => Text -> Object -> Maybe a
lookupKey Text
"testing_tag" Object
obj
  Release -> Maybe Release
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Release -> Maybe Release) -> Release -> Maybe Release
forall a b. (a -> b) -> a -> b
$ String
-> String
-> String
-> String
-> Bool
-> String
-> String
-> Maybe String
-> String
-> Bool
-> Maybe String
-> String
-> Release
Release String
name String
ver String
idPref String
br Bool
composed String
candidate String
disttag Maybe String
setting String
state Bool
automatic Maybe String
testrepo String
testtag

-- | ordered by releaseName
instance Ord Release where
  compare :: Release -> Release -> Ordering
compare Release
r1 Release
r2 =
    String -> String -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Release -> String
releaseName Release
r1) (Release -> String
releaseName Release
r2)

-- FIXME remove containers and flatpaks
-- | Get list of all current Fedora Project releases (from Bodhi)
getActiveReleases :: IO [Release]
getActiveReleases :: IO [Release]
getActiveReleases =
  (Object -> Maybe Release) -> [Object] -> [Release]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Object -> Maybe Release
readRelease ([Object] -> [Release]) -> IO [Object] -> IO [Release]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [Object]
getBodhiReleases

-- getProductReleases :: String -> IO [Release]
-- getProductReleases name =
--   mapMaybe readRelease <$> getBodhiProductReleases name

-- | Get list of current Fedora Linux releases
getFedoraReleases :: IO [Release]
getFedoraReleases :: IO [Release]
getFedoraReleases =
  (Object -> Maybe Release) -> [Object] -> [Release]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Object -> Maybe Release
readRelease ([Object] -> [Release]) -> IO [Object] -> IO [Release]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [Object]
getBodhiFedoraReleases

-- | Get list of current Fedora EPEL releases
getEPELReleases :: IO [Release]
getEPELReleases :: IO [Release]
getEPELReleases =
  (Object -> Maybe Release) -> [Object] -> [Release]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Object -> Maybe Release
readRelease ([Object] -> [Release]) -> IO [Object] -> IO [Release]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [Object]
getBodhiEPELReleases

-- releaseFilter :: (Release -> a) -> (a -> Bool) -> [Release] -> [Release]
-- releaseFilter f p = filter (p . f)

-- | Get the Release for an active Branch
--
-- Errors for an inactive Branch
getBranchRelease :: String -> IO Release
getBranchRelease :: String -> IO Release
getBranchRelease String
br = do
  [Release]
rels <- (Object -> Maybe Release) -> [Object] -> [Release]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Object -> Maybe Release
readRelease ([Object] -> [Release]) -> IO [Object] -> IO [Release]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO [Object]
getBodhiBranchReleases String
br
  case [Release]
rels of
    [] -> String -> IO Release
forall a. HasCallStack => String -> a
error (String -> IO Release) -> String -> IO Release
forall a b. (a -> b) -> a -> b
$ String
"release not found for branch " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
br
    [Release
rel] -> Release -> IO Release
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Release
rel
    [Release]
_ -> String -> IO Release
forall a. HasCallStack => String -> a
error (String -> IO Release) -> String -> IO Release
forall a b. (a -> b) -> a -> b
$ String
"multiple releases for " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
br String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":\n" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords ((Release -> String) -> [Release] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Release -> String
releaseName [Release]
rels)