module Music.Theory.Time.Notation where
import Data.List.Split
import Text.Printf
type FSEC = Double
type MinSec n = (n,n)
type MINSEC = (Int,Int)
type MinCsec n = (n,n,n)
type MINCSEC = (Int,Int,Int)
sec_to_minsec :: Integral n => n -> MinSec n
sec_to_minsec = flip divMod 60
minsec_to_sec :: Num n => MinSec n -> n
minsec_to_sec (m,s) = m * 60 + s
minsec_binop :: Integral t => (t -> t -> t) -> MinSec t -> MinSec t -> MinSec t
minsec_binop f p q = sec_to_minsec (f (minsec_to_sec p) (minsec_to_sec q))
minsec_sub :: Integral n => MinSec n -> MinSec n -> MinSec n
minsec_sub = minsec_binop ()
minsec_diff :: Integral n => MinSec n -> MinSec n -> MinSec n
minsec_diff = minsec_binop subtract
minsec_add :: Integral n => MinSec n -> MinSec n -> MinSec n
minsec_add = minsec_binop (+)
minsec_sum :: Integral n => [MinSec n] -> MinSec n
minsec_sum = foldl minsec_add (0,0)
fsec_to_minsec :: FSEC -> MINSEC
fsec_to_minsec = sec_to_minsec . round
minsec_pp :: MINSEC -> String
minsec_pp (m,s) = printf "%02d:%02d" m s
minsec_parse :: (Num n,Read n) => String -> MinSec n
minsec_parse x =
case splitOn ":" x of
[m,s] -> (read m,read s)
_ -> error "parse_minsec"
fsec_to_mincsec :: FSEC -> MINCSEC
fsec_to_mincsec tm =
let tm' = floor tm
(m,s) = sec_to_minsec tm'
cs = round ((tm fromIntegral tm') * 100)
in (m,s,cs)
mincsec_to_fsec :: Real n => MinCsec n -> FSEC
mincsec_to_fsec (m,s,cs) = realToFrac m * 60 + realToFrac s + (realToFrac cs / 100)
mincsec_to_csec :: Num n => MinCsec n -> n
mincsec_to_csec (m,s,cs) = m * 60 * 100 + s * 100 + cs
csec_to_mincsec :: Integral n => n -> MinCsec n
csec_to_mincsec csec =
let (m,cs) = csec `divMod` 6000
(s,cs') = cs `divMod` 100
in (m,s,cs')
mincsec_pp_opt :: Bool -> MINCSEC -> String
mincsec_pp_opt concise (m,s,cs) =
if concise && cs == 0
then printf "%02d:%02d" m s
else printf "%02d:%02d.%02d" m s cs
mincsec_pp :: MINCSEC -> String
mincsec_pp = mincsec_pp_opt False
mincsec_binop :: Integral t => (t -> t -> t) -> MinCsec t -> MinCsec t -> MinCsec t
mincsec_binop f p q = csec_to_mincsec (f (mincsec_to_csec p) (mincsec_to_csec q))
span_pp :: (t -> String) -> (t,t) -> String
span_pp f (t1,t2) = concat [f t1," - ",f t2]