{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, You can
   obtain one at https://mozilla.org/MPL/2.0/. -}

-- | Contains data describing packages, methods to update them and to request
-- information about them.
module SlackBuilder.Package
    ( DataBaseEntry(..)
    , Download(..)
    , DownloadTemplate(..)
    , PackageDescription(..)
    , PackageUpdateData(..)
    , Updater(..)
    , renderDownloadWithVersion
    , renderTextWithVersion
    ) where

import Data.Text (Text)
import qualified Data.Text as Text
import Text.URI (URI(..))
import qualified Text.URI as URI
import Crypto.Hash (Digest, MD5)
import SlackBuilder.Trans
import Control.Monad.Catch (MonadThrow)
import Data.Map (Map)

-- | Contains information how a package can be updated.
data PackageDescription = PackageDescription
    { latest :: Updater
    , downloaders :: Map Text Updater
    , name :: Text
    }

data PackageUpdateData = PackageUpdateData
    { description :: PackageDescription
    , category :: Text
    , version :: Text
    }

-- | Download URI with the MD5 checksum of the target.
data Download = Download
    { download :: URI
    , md5sum :: Digest MD5
    } deriving (Eq, Show)

-- | List of URI components, including version placeholders.
newtype DownloadTemplate = DownloadTemplate
    { unDownloadTemplate :: Text
    } deriving Eq

instance Show DownloadTemplate
  where
    show = Text.unpack . unDownloadTemplate

-- | Replaces placeholders in the URL template with the given version.
renderDownloadWithVersion :: MonadThrow m => DownloadTemplate -> Text -> m URI
renderDownloadWithVersion (DownloadTemplate template) version =
    URI.mkURI $ renderTextWithVersion template version

-- | Replaces placeholders in the text with the given version.
renderTextWithVersion :: Text -> Text -> Text
renderTextWithVersion template version = Text.replace "{version}" version template

-- | Function used to get the latest version of a source.
data Updater = Updater
    { detectLatest :: SlackBuilderT (Maybe Text)
    , is64 :: Bool
    , getVersion :: Text -> Text -> SlackBuilderT Download
    }

data DataBaseEntry = DataBaseEntry
    { name :: Text
    , version :: Text
    , arch :: Text
    , build :: Text
    } deriving Eq

instance Show DataBaseEntry
  where
    show DataBaseEntry{..} = Text.unpack
        $ Text.intercalate "-" [name, version, arch, build]