{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TemplateHaskell #-}

module Data.Aviation.Casr.Logbook.Reports.Meta.ExpenseReport(
  ExpenseReport(ExpenseReport)
, HasExpenseReport(..)
, entryExpenseReport
, logbookExpenseReport
) where

import Control.Category((.))
import Control.Lens(makeClassy, (^.), _Wrapped)
import Control.Monad((>>=), return)
import Data.Aviation.Casr.Logbook.Types.Entry
    ( Entry(AircraftFlightEntry, SimulatorFlightEntry, ExamEntry,
            BriefingEntry) )
import Data.Aviation.Casr.Logbook.Types.Logbook
    ( Logbook, logbookentries )
import Data.Aviation.Casr.Logbook.Meta.AircraftFlightExpense
    ( AircraftFlightExpense(ExpenseAircraftUsage,
                            ExpenseAircraftLanding) )
import Data.Aviation.Casr.Logbook.Meta.AircraftFlightMeta
    ( AircraftFlightMeta, expenses )
import Data.Aviation.Casr.Logbook.Meta.AircraftLandingExpense
    ( aircraftlandingexpenseamount )
import Data.Aviation.Casr.Logbook.Meta.AircraftUsageExpense
    ( aircraftUsageCost )
import Data.Aviation.Casr.Logbook.Meta.BriefingExpense
    ( briefingCost )
import Data.Aviation.Casr.Logbook.Meta.BriefingMeta
    ( BriefingMeta )
import Data.Aviation.Casr.Logbook.Meta.ExamExpense
    ( examexpenseamount )
import Data.Aviation.Casr.Logbook.Meta.ExamMeta ( ExamMeta )
import Data.Aviation.Casr.Logbook.Meta.SimulatorFlightExpense
    ( simulatorFlightCost )
import Data.Aviation.Casr.Logbook.Meta.SimulatorFlightMeta
    ( SimulatorFlightMeta )
import Data.Eq(Eq)
import Data.Foldable(sum, foldMap)
import Data.Function(($))
import Data.Int(Int)
import Data.Monoid(Monoid(mempty, mappend))
import Data.Ord(Ord)
import Data.Semigroup(Semigroup((<>)))
import Prelude(Show, (+))

data ExpenseReport =
  ExpenseReport {
    ExpenseReport -> Int
_aircraftUsageExpenseTotal :: Int
  , ExpenseReport -> Int
_aircraftLandingExpenseTotal :: Int
  , ExpenseReport -> Int
_briefingExpenseTotal :: Int
  , ExpenseReport -> Int
_examExpenseTotal :: Int
  , ExpenseReport -> Int
_simulatorFlightTotal :: Int
  } deriving (ExpenseReport -> ExpenseReport -> Bool
(ExpenseReport -> ExpenseReport -> Bool)
-> (ExpenseReport -> ExpenseReport -> Bool) -> Eq ExpenseReport
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExpenseReport -> ExpenseReport -> Bool
== :: ExpenseReport -> ExpenseReport -> Bool
$c/= :: ExpenseReport -> ExpenseReport -> Bool
/= :: ExpenseReport -> ExpenseReport -> Bool
Eq, Eq ExpenseReport
Eq ExpenseReport =>
(ExpenseReport -> ExpenseReport -> Ordering)
-> (ExpenseReport -> ExpenseReport -> Bool)
-> (ExpenseReport -> ExpenseReport -> Bool)
-> (ExpenseReport -> ExpenseReport -> Bool)
-> (ExpenseReport -> ExpenseReport -> Bool)
-> (ExpenseReport -> ExpenseReport -> ExpenseReport)
-> (ExpenseReport -> ExpenseReport -> ExpenseReport)
-> Ord ExpenseReport
ExpenseReport -> ExpenseReport -> Bool
ExpenseReport -> ExpenseReport -> Ordering
ExpenseReport -> ExpenseReport -> ExpenseReport
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ExpenseReport -> ExpenseReport -> Ordering
compare :: ExpenseReport -> ExpenseReport -> Ordering
$c< :: ExpenseReport -> ExpenseReport -> Bool
< :: ExpenseReport -> ExpenseReport -> Bool
$c<= :: ExpenseReport -> ExpenseReport -> Bool
<= :: ExpenseReport -> ExpenseReport -> Bool
$c> :: ExpenseReport -> ExpenseReport -> Bool
> :: ExpenseReport -> ExpenseReport -> Bool
$c>= :: ExpenseReport -> ExpenseReport -> Bool
>= :: ExpenseReport -> ExpenseReport -> Bool
$cmax :: ExpenseReport -> ExpenseReport -> ExpenseReport
max :: ExpenseReport -> ExpenseReport -> ExpenseReport
$cmin :: ExpenseReport -> ExpenseReport -> ExpenseReport
min :: ExpenseReport -> ExpenseReport -> ExpenseReport
Ord, Int -> ExpenseReport -> ShowS
[ExpenseReport] -> ShowS
ExpenseReport -> String
(Int -> ExpenseReport -> ShowS)
-> (ExpenseReport -> String)
-> ([ExpenseReport] -> ShowS)
-> Show ExpenseReport
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExpenseReport -> ShowS
showsPrec :: Int -> ExpenseReport -> ShowS
$cshow :: ExpenseReport -> String
show :: ExpenseReport -> String
$cshowList :: [ExpenseReport] -> ShowS
showList :: [ExpenseReport] -> ShowS
Show)

makeClassy ''ExpenseReport

instance Semigroup ExpenseReport where
  ExpenseReport Int
ag1 Int
al1 Int
b1 Int
e1 Int
s1 <> :: ExpenseReport -> ExpenseReport -> ExpenseReport
<> ExpenseReport Int
ag2 Int
al2 Int
b2 Int
e2 Int
s2 =
    Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport (Int
ag1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
ag2) (Int
al1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
al2) (Int
b1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
b2) (Int
e1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e2) (Int
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
s2)

instance Monoid ExpenseReport where
  mempty :: ExpenseReport
mempty =
    Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport Int
0 Int
0 Int
0 Int
0 Int
0
  mappend :: ExpenseReport -> ExpenseReport -> ExpenseReport
mappend =
    ExpenseReport -> ExpenseReport -> ExpenseReport
forall a. Semigroup a => a -> a -> a
(<>)

entryExpenseReport ::
  Entry AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
  -> ExpenseReport
entryExpenseReport :: Entry AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> ExpenseReport
entryExpenseReport (AircraftFlightEntry AircraftFlight
fl AircraftFlightMeta
e) =
  let usage :: Int
usage =
        [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ AircraftFlightMeta
e AircraftFlightMeta
-> Getting
     [AircraftFlightExpense] AircraftFlightMeta [AircraftFlightExpense]
-> [AircraftFlightExpense]
forall s a. s -> Getting a s a -> a
^. Getting
  [AircraftFlightExpense] AircraftFlightMeta [AircraftFlightExpense]
forall c.
HasAircraftFlightMeta c =>
Lens' c [AircraftFlightExpense]
Lens' AircraftFlightMeta [AircraftFlightExpense]
expenses [AircraftFlightExpense]
-> (AircraftFlightExpense -> [Int]) -> [Int]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \AircraftFlightExpense
p ->
          case AircraftFlightExpense
p of
            ExpenseAircraftUsage AircraftUsageExpense
e' -> [AircraftFlight -> AircraftUsageExpense -> Int
forall s. HasAircraftFlight s => s -> AircraftUsageExpense -> Int
aircraftUsageCost AircraftFlight
fl AircraftUsageExpense
e']
            ExpenseAircraftLanding AircraftLandingExpense
_ -> []
      landing :: Int
landing =
        [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ AircraftFlightMeta
e AircraftFlightMeta
-> Getting
     [AircraftFlightExpense] AircraftFlightMeta [AircraftFlightExpense]
-> [AircraftFlightExpense]
forall s a. s -> Getting a s a -> a
^. Getting
  [AircraftFlightExpense] AircraftFlightMeta [AircraftFlightExpense]
forall c.
HasAircraftFlightMeta c =>
Lens' c [AircraftFlightExpense]
Lens' AircraftFlightMeta [AircraftFlightExpense]
expenses [AircraftFlightExpense]
-> (AircraftFlightExpense -> [Int]) -> [Int]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \AircraftFlightExpense
p ->
          case AircraftFlightExpense
p of
            ExpenseAircraftUsage AircraftUsageExpense
_ -> []
            ExpenseAircraftLanding AircraftLandingExpense
l -> [AircraftLandingExpense
l AircraftLandingExpense
-> Getting Int AircraftLandingExpense Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int AircraftLandingExpense Int
forall c. HasAircraftLandingExpense c => Lens' c Int
Lens' AircraftLandingExpense Int
aircraftlandingexpenseamount]
  in  Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport
        Int
usage
        Int
landing
        Int
0
        Int
0
        Int
0
entryExpenseReport (SimulatorFlightEntry SimulatorFlight
fl SimulatorFlightMeta
e) =
  Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport
    Int
0
    Int
0
    Int
0
    Int
0
    ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ SimulatorFlightMeta
e SimulatorFlightMeta
-> Getting
     [SimulatorFlightExpense]
     SimulatorFlightMeta
     [SimulatorFlightExpense]
-> [SimulatorFlightExpense]
forall s a. s -> Getting a s a -> a
^. Getting
  [SimulatorFlightExpense]
  SimulatorFlightMeta
  [SimulatorFlightExpense]
(Unwrapped SimulatorFlightMeta
 -> Const [SimulatorFlightExpense] (Unwrapped SimulatorFlightMeta))
-> SimulatorFlightMeta
-> Const [SimulatorFlightExpense] SimulatorFlightMeta
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SimulatorFlightMeta
  SimulatorFlightMeta
  (Unwrapped SimulatorFlightMeta)
  (Unwrapped SimulatorFlightMeta)
_Wrapped [SimulatorFlightExpense]
-> (SimulatorFlightExpense -> [Int]) -> [Int]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> [Int]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> [Int])
-> (SimulatorFlightExpense -> Int)
-> SimulatorFlightExpense
-> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. SimulatorFlight -> SimulatorFlightExpense -> Int
forall s.
HasSimulatorFlight s =>
s -> SimulatorFlightExpense -> Int
simulatorFlightCost SimulatorFlight
fl)
entryExpenseReport (ExamEntry Exam
_ ExamMeta
e) =
  Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport
    Int
0
    Int
0
    Int
0
    ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ ExamMeta
e ExamMeta
-> Getting [ExamExpense] ExamMeta [ExamExpense] -> [ExamExpense]
forall s a. s -> Getting a s a -> a
^. Getting [ExamExpense] ExamMeta [ExamExpense]
(Unwrapped ExamMeta -> Const [ExamExpense] (Unwrapped ExamMeta))
-> ExamMeta -> Const [ExamExpense] ExamMeta
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso ExamMeta ExamMeta (Unwrapped ExamMeta) (Unwrapped ExamMeta)
_Wrapped [ExamExpense] -> (ExamExpense -> [Int]) -> [Int]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> [Int]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> [Int]) -> (ExamExpense -> Int) -> ExamExpense -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ExamExpense -> Getting Int ExamExpense Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ExamExpense Int
forall c. HasExamExpense c => Lens' c Int
Lens' ExamExpense Int
examexpenseamount))
    Int
0
entryExpenseReport (BriefingEntry Briefing
br BriefingMeta
e) =
  Int -> Int -> Int -> Int -> Int -> ExpenseReport
ExpenseReport
    Int
0
    Int
0
    ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ BriefingMeta
e BriefingMeta
-> Getting [BriefingExpense] BriefingMeta [BriefingExpense]
-> [BriefingExpense]
forall s a. s -> Getting a s a -> a
^. Getting [BriefingExpense] BriefingMeta [BriefingExpense]
(Unwrapped BriefingMeta
 -> Const [BriefingExpense] (Unwrapped BriefingMeta))
-> BriefingMeta -> Const [BriefingExpense] BriefingMeta
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  BriefingMeta
  BriefingMeta
  (Unwrapped BriefingMeta)
  (Unwrapped BriefingMeta)
_Wrapped [BriefingExpense] -> (BriefingExpense -> [Int]) -> [Int]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> [Int]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> [Int])
-> (BriefingExpense -> Int) -> BriefingExpense -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Briefing -> BriefingExpense -> Int
forall s. HasBriefing s => s -> BriefingExpense -> Int
briefingCost Briefing
br)
    Int
0
    Int
0

logbookExpenseReport ::
  Logbook AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
  -> ExpenseReport
logbookExpenseReport :: Logbook
  AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> ExpenseReport
logbookExpenseReport Logbook
  AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
b =
  (Entry AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
 -> ExpenseReport)
-> [Entry
      AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
-> ExpenseReport
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Entry AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> ExpenseReport
entryExpenseReport (Logbook
  AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
b Logbook
  AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> Getting
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     (Logbook
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
-> [Entry
      AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
forall s a. s -> Getting a s a -> a
^. (Entries
   AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
 -> Const
      [Entry
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
      (Entries
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
-> Logbook
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> Const
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     (Logbook
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
forall c ae se ee be.
HasLogbook c ae se ee be =>
Lens' c (Entries ae se ee be)
Lens'
  (Logbook
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
  (Entries
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
logbookentries ((Entries
    AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
  -> Const
       [Entry
          AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
       (Entries
          AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
 -> Logbook
      AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
 -> Const
      [Entry
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
      (Logbook
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
-> (([Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     -> Const
          [Entry
             AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
          [Entry
             AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta])
    -> Entries
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
    -> Const
         [Entry
            AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
         (Entries
            AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
-> Getting
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     (Logbook
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ([Entry
    AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
 -> Const
      [Entry
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
      [Entry
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta])
-> Entries
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> Const
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     (Entries
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
(Unwrapped
   (Entries
      AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
 -> Const
      [Entry
         AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
      (Unwrapped
         (Entries
            AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)))
-> Entries
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta
-> Const
     [Entry
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta]
     (Entries
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  (Entries
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
  (Entries
     AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta)
  (Unwrapped
     (Entries
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
  (Unwrapped
     (Entries
        AircraftFlightMeta SimulatorFlightMeta ExamMeta BriefingMeta))
_Wrapped)