{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}

module Data.Aviation.Casr.Logbook.Types.TimeAmount(
  TimeAmount(..)
, HasTimeAmount(..)
, parttimeamount
, zerotimeamount
, addtimeamount
, timeAmountBy10
) where

import Data.Bool(Bool, bool)
import Data.Maybe(fromMaybe)
import Data.Ord((>))
import Data.Semigroup(Semigroup((<>)))
import Prelude(Integral, divMod, mod)
import Control.Lens(makeClassy, (^?), over, _1, ( # ))
import Data.Eq(Eq)
import Data.Digit(DecDigit, x0, x1, integralDecimal)
import Data.Int(Int)
import Data.Monoid(Monoid(mempty, mappend))
import Data.Ord(Ord)
import Prelude(Show, Num((+), (*)))

data TimeAmount =
  TimeAmount {
    _hours :: Int
  , _tenthofhour :: DecDigit
  } deriving (Eq, Ord, Show)

makeClassy ''TimeAmount

parttimeamount ::
  DecDigit
  -> TimeAmount
parttimeamount =
  TimeAmount 0

zerotimeamount ::
  TimeAmount
zerotimeamount =
  TimeAmount 0 x0

addtimeamount ::
  TimeAmount
  -> TimeAmount
  -> TimeAmount
TimeAmount f1 p1 `addtimeamount` TimeAmount f2 p2 =
  let (h, q) = p1 /+/ p2
  in  TimeAmount (f1 + f2 + integralDecimal # (h :: DecDigit)) q

timeAmountBy10 ::
  TimeAmount
  -> Int
timeAmountBy10 (TimeAmount a b) =
  a * 10 + integralDecimal # b

instance Semigroup TimeAmount where
  (<>) =
    addtimeamount

instance Monoid TimeAmount where
  mempty =
    zerotimeamount
  mappend =
    (<>)

---- belongs in digit package

mod10 ::
  Integral a =>
  a
  -> DecDigit
mod10 n =
  let r = n `mod` 10
  in fromMaybe (mod10 r) (r ^? integralDecimal)

addDecDigit ::
  DecDigit
  -> DecDigit
  -> (Bool, DecDigit)
addDecDigit a b =
  let (x, r) =
        (integralDecimal # a + integralDecimal # b) `divMod` 10
  in  (x > 0, mod10 (r :: Int))

(/+/) ::
  DecDigit
  -> DecDigit
  -> (DecDigit, DecDigit)
(/+/) a b =
  over _1 (bool x0 x1) (addDecDigit a b)