module Hydrogen.Version (
    Version
  , mkVersion
  , refineVersion
  , majorVersion
  , minorVersion
  , patchVersion
  , tailVersion
  , fromDataVersion
  , toDataVersion
  ) where

import Prelude

import Data.List (intersperse)
import Data.Char (isDigit)
import Data.Typeable
import qualified Data.Version as V

import GHC.Generics

newtype Version = Version [Integer]
  deriving (Generic, Typeable)

instance Eq Version where
    v1 == v2 = compare v1 v2 == EQ

instance Ord Version where
    compare (Version v1) (Version v2) = case (v1, v2) of
        ([], []) -> EQ
        (xs, []) -> if all (== 0) xs then EQ else GT
        ([], ys) -> if all (== 0) ys then EQ else LT
        (x : xs, y : ys) | x == y -> compare (Version xs) (Version ys)
        (x : _, y : _) -> compare x y

instance Show Version where
    show (Version v) = concat (intersperse "." (map show v))

instance Read Version where
    readsPrec _ xs = case span isDigit xs of
        ([], _) -> []
        (vs, []) -> result vs ""
        (vs, '.' : rs) -> case reads rs of
            [(Version vs', rs')] -> [(Version (read vs : vs'), rs')]
            _ -> result vs rs
        (vs, rs) -> result vs rs
      where
        result vs rs = [(Version [read vs], rs)]

majorVersion, minorVersion, patchVersion :: Version -> Integer

majorVersion (Version (v : _)) = v
majorVersion _ = 0

minorVersion (Version (_ : v : _)) = v
minorVersion _ = 0

patchVersion (Version (_ : _ : v : _)) = v
patchVersion _ = 0

tailVersion :: Version -> [Integer]

tailVersion (Version (_ : _ : _ : vs)) = vs
tailVersion _ = []

mkVersion :: Integer -> Integer -> Integer -> Version
mkVersion a b c = Version [a, b, c]

refineVersion :: Version -> Integer -> Version
refineVersion (Version v) i = Version (v ++ [i])

fromDataVersion :: V.Version -> Version
fromDataVersion = Version . map fromIntegral . V.versionBranch

toDataVersion :: Version -> V.Version
toDataVersion (Version v) = V.Version {
    V.versionBranch = map fromInteger v
  , V.versionTags = []
  }