{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

module Tax.Canada.Federal.Schedule11 where

import Data.Fixed (Centi)
import Data.Text (Text)
import Language.Haskell.TH qualified as TH
import Rank2 qualified
import Rank2.TH qualified
import Transformation.Shallow.TH qualified

import Tax.Canada.Shared (SubCalculation(result), fixSubCalculation, subCalculationFields)
import Tax.Canada.T1.Types (T1)
import Tax.Canada.T1.Types qualified
import Tax.FDF (Entry (Amount, Checkbox, Count), FieldConst (Field), within)
import Tax.Util (fixEq, fractionOf, difference, nonNegativeDifference, totalOf)

data Schedule11 line = Schedule11{
   forall (line :: * -> *). Schedule11 line -> Page1 line
page1 :: Page1 line,
   forall (line :: * -> *). Schedule11 line -> Page2 line
page2 :: Page2 line}

data Page1 line = Page1{
   forall (line :: * -> *). Page1 line -> line Centi
line_32000_tuition :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line2_copy :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line2_fraction :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line3_limit :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line4_min :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line5_trainingClaim :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line6_difference :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line_32001_eligible :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line8_sum :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line9_pastUnused :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line10_sum :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line11_copy :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line11_numerator :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line12_copy :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line13_difference :: line Centi,
   forall (line :: * -> *). Page1 line -> SubCalculation line
line14_minUnused :: SubCalculation line,
   forall (line :: * -> *). Page1 line -> line Centi
line15_difference :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line16_min :: line Centi,
   forall (line :: * -> *). Page1 line -> line Centi
line17_sum :: line Centi}

data Page2 line = Page2{
   forall (line :: * -> *). Page2 line -> line Bool
line_32005_diability :: line Bool,
   forall (line :: * -> *). Page2 line -> line Word
line_32010_partTimeMonths :: line Word,
   forall (line :: * -> *). Page2 line -> line Word
line_32020_fullTimeMonths :: line Word,
   forall (line :: * -> *). Page2 line -> line Centi
line18_copy :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line19_copy :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line20_difference :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line21_copy :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line22_copy :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line23_difference :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line24_transferred :: line Centi,
   forall (line :: * -> *). Page2 line -> line Centi
line25_difference :: line Centi}

$(foldMap
   (\t-> concat <$> sequenceA [
       [d|
           deriving instance (Show (line Bool), Show (line Centi),
                              Show (line Rational), Show (line Word)) => Show ($(TH.conT t) line)
           deriving instance (Eq (line Bool), Eq (line Centi),
                              Eq (line Rational), Eq (line Word)) => Eq ($(TH.conT t) line)
       |],
       Rank2.TH.deriveAll t,
       Transformation.Shallow.TH.deriveAll t])
   [''Schedule11, ''Page1, ''Page2])

fixSchedule11 :: T1 Maybe -> Schedule11 Maybe -> Schedule11 Maybe
fixSchedule11 :: T1 Maybe -> Schedule11 Maybe -> Schedule11 Maybe
fixSchedule11 T1 Maybe
t1 = (Schedule11 Maybe -> Schedule11 Maybe)
-> Schedule11 Maybe -> Schedule11 Maybe
forall a. Eq a => (a -> a) -> a -> a
fixEq ((Schedule11 Maybe -> Schedule11 Maybe)
 -> Schedule11 Maybe -> Schedule11 Maybe)
-> (Schedule11 Maybe -> Schedule11 Maybe)
-> Schedule11 Maybe
-> Schedule11 Maybe
forall a b. (a -> b) -> a -> b
$ \Schedule11{$sel:page1:Schedule11 :: forall (line :: * -> *). Schedule11 line -> Page1 line
page1 = page1 :: Page1 Maybe
page1@Page1{Maybe Centi
SubCalculation Maybe
$sel:line_32000_tuition:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line2_copy:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line2_fraction:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line3_limit:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line4_min:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line5_trainingClaim:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line6_difference:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line_32001_eligible:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line8_sum:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line9_pastUnused:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line10_sum:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line11_copy:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line11_numerator:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line12_copy:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line13_difference:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line14_minUnused:Page1 :: forall (line :: * -> *). Page1 line -> SubCalculation line
$sel:line15_difference:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line16_min:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
$sel:line17_sum:Page1 :: forall (line :: * -> *). Page1 line -> line Centi
line_32000_tuition :: Maybe Centi
line2_copy :: Maybe Centi
line2_fraction :: Maybe Centi
line3_limit :: Maybe Centi
line4_min :: Maybe Centi
line5_trainingClaim :: Maybe Centi
line6_difference :: Maybe Centi
line_32001_eligible :: Maybe Centi
line8_sum :: Maybe Centi
line9_pastUnused :: Maybe Centi
line10_sum :: Maybe Centi
line11_copy :: Maybe Centi
line11_numerator :: Maybe Centi
line12_copy :: Maybe Centi
line13_difference :: Maybe Centi
line14_minUnused :: SubCalculation Maybe
line15_difference :: Maybe Centi
line16_min :: Maybe Centi
line17_sum :: Maybe Centi
..}, $sel:page2:Schedule11 :: forall (line :: * -> *). Schedule11 line -> Page2 line
page2 = page2 :: Page2 Maybe
page2@Page2{Maybe Bool
Maybe Word
Maybe Centi
$sel:line_32005_diability:Page2 :: forall (line :: * -> *). Page2 line -> line Bool
$sel:line_32010_partTimeMonths:Page2 :: forall (line :: * -> *). Page2 line -> line Word
$sel:line_32020_fullTimeMonths:Page2 :: forall (line :: * -> *). Page2 line -> line Word
$sel:line18_copy:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line19_copy:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line20_difference:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line21_copy:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line22_copy:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line23_difference:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line24_transferred:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
$sel:line25_difference:Page2 :: forall (line :: * -> *). Page2 line -> line Centi
line_32005_diability :: Maybe Bool
line_32010_partTimeMonths :: Maybe Word
line_32020_fullTimeMonths :: Maybe Word
line18_copy :: Maybe Centi
line19_copy :: Maybe Centi
line20_difference :: Maybe Centi
line21_copy :: Maybe Centi
line22_copy :: Maybe Centi
line23_difference :: Maybe Centi
line24_transferred :: Maybe Centi
line25_difference :: Maybe Centi
..}} -> Schedule11{
   $sel:page1:Schedule11 :: Page1 Maybe
page1 = Page1 Maybe
page1{
      line2_copy = line_32000_tuition,
      line2_fraction = (0.5 *) <$> line2_copy,
      line4_min = minimum [line2_fraction, line3_limit],
      line6_difference = difference line_32000_tuition line5_trainingClaim,
      line8_sum = totalOf [line6_difference, line_32001_eligible],
      line10_sum = totalOf [line9_pastUnused, line8_sum],
      line11_copy = if taxableIncomeUnderThreshold then Nothing else t1.page7.partC_NetFederalTax.line116,
      line11_numerator = if taxableIncomeUnderThreshold then taxableIncome else (/ 0.15) <$> line11_copy,
      line12_copy = t1.page6.line99,
      line13_difference = nonNegativeDifference line11_numerator line12_copy,
      line14_minUnused = fixSubCalculation $ minimum [line9_pastUnused, line13_difference],
      line15_difference = difference line13_difference line14_minUnused.result,
      line16_min = minimum [line8_sum, line15_difference],
      line17_sum = totalOf [line14_minUnused.result, line16_min]},
   $sel:page2:Schedule11 :: Page2 Maybe
page2 = Page2 Maybe
page2{
      line18_copy = line10_sum,
      line19_copy = line17_sum,
      line20_difference = difference line18_copy line19_copy,
      line21_copy = min 5000 <$> line8_sum,
      line22_copy = line16_min,
      line23_difference = nonNegativeDifference line21_copy line22_copy,
      line25_difference = nonNegativeDifference line20_difference line24_transferred}}
   where taxableIncome :: Maybe Centi
taxableIncome = T1 Maybe
t1.page5.step4_TaxableIncome.line_26000_TaxableIncome
         taxableIncomeUnderThreshold :: Bool
taxableIncomeUnderThreshold = Maybe Centi
taxableIncome Maybe Centi -> Maybe Centi -> Bool
forall a. Ord a => a -> a -> Bool
<= Centi -> Maybe Centi
forall a. a -> Maybe a
Just Centi
50_197

schedule11Fields :: Schedule11 FieldConst
schedule11Fields :: Schedule11 FieldConst
schedule11Fields = Text -> FieldConst a -> FieldConst a
forall x. Text -> FieldConst x -> FieldConst x
within Text
"form1" (forall {a}. FieldConst a -> FieldConst a)
-> Schedule11 FieldConst -> Schedule11 FieldConst
forall {k} (g :: (k -> *) -> *) (p :: k -> *) (q :: k -> *).
Functor g =>
(forall (a :: k). p a -> q a) -> g p -> g q
forall (p :: * -> *) (q :: * -> *).
(forall a. p a -> q a) -> Schedule11 p -> Schedule11 q
Rank2.<$> Schedule11 {
   $sel:page1:Schedule11 :: Page1 FieldConst
page1 = Page1 FieldConst
page1Fields,
   $sel:page2:Schedule11 :: Page2 FieldConst
page2 = Page2 FieldConst
page2Fields}

page1Fields :: Page1 FieldConst
page1Fields :: Page1 FieldConst
page1Fields = Text -> FieldConst a -> FieldConst a
forall x. Text -> FieldConst x -> FieldConst x
within Text
"Page1"  (FieldConst a -> FieldConst a)
-> (FieldConst a -> FieldConst a) -> FieldConst a -> FieldConst a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FieldConst a -> FieldConst a
forall x. Text -> FieldConst x -> FieldConst x
within Text
"YourTuition" (forall {a}. FieldConst a -> FieldConst a)
-> Page1 FieldConst -> Page1 FieldConst
forall {k} (g :: (k -> *) -> *) (p :: k -> *) (q :: k -> *).
Functor g =>
(forall (a :: k). p a -> q a) -> g p -> g q
forall (p :: * -> *) (q :: * -> *).
(forall a. p a -> q a) -> Page1 p -> Page1 q
Rank2.<$> Page1 {
   $sel:line_32000_tuition:Page1 :: FieldConst Centi
line_32000_tuition = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line1", Text
"Amount2"] Entry Centi
Amount,
   $sel:line2_copy:Page1 :: FieldConst Centi
line2_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line2", Text
"Amount1"] Entry Centi
Amount,
   $sel:line2_fraction:Page1 :: FieldConst Centi
line2_fraction = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line2", Text
"Amount2"] Entry Centi
Amount,
   $sel:line3_limit:Page1 :: FieldConst Centi
line3_limit = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line3", Text
"Amount4"] Entry Centi
Amount,
   $sel:line4_min:Page1 :: FieldConst Centi
line4_min = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line4", Text
"Amount5"] Entry Centi
Amount,
   $sel:line5_trainingClaim:Page1 :: FieldConst Centi
line5_trainingClaim = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line5", Text
"Amount6"] Entry Centi
Amount,
   $sel:line6_difference:Page1 :: FieldConst Centi
line6_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line6", Text
"Amount7"] Entry Centi
Amount,
   $sel:line_32001_eligible:Page1 :: FieldConst Centi
line_32001_eligible = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line7", Text
"Amount8"] Entry Centi
Amount,
   $sel:line8_sum:Page1 :: FieldConst Centi
line8_sum = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line8", Text
"Amount1"] Entry Centi
Amount,
   $sel:line9_pastUnused:Page1 :: FieldConst Centi
line9_pastUnused = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line9", Text
"Amount1"] Entry Centi
Amount,
   $sel:line10_sum:Page1 :: FieldConst Centi
line10_sum = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line10", Text
"Amount10"] Entry Centi
Amount,
   $sel:line11_copy:Page1 :: FieldConst Centi
line11_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line11", Text
"Line11", Text
"Amount11"] Entry Centi
Amount,
   $sel:line11_numerator:Page1 :: FieldConst Centi
line11_numerator = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line11", Text
"Amount11"] Entry Centi
Amount,
   $sel:line12_copy:Page1 :: FieldConst Centi
line12_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line12", Text
"Amount12"] Entry Centi
Amount,
   $sel:line13_difference:Page1 :: FieldConst Centi
line13_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line13", Text
"Amount13"] Entry Centi
Amount,
   $sel:line14_minUnused:Page1 :: SubCalculation FieldConst
line14_minUnused = Text -> [Text] -> [Text] -> SubCalculation FieldConst
subCalculationFields Text
"Line14" [Text
"Amount1"] [Text
"Amount14"],
   $sel:line15_difference:Page1 :: FieldConst Centi
line15_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line15", Text
"Amount15"] Entry Centi
Amount,
   $sel:line16_min:Page1 :: FieldConst Centi
line16_min = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line16", Text
"Amount16"] Entry Centi
Amount,
   $sel:line17_sum:Page1 :: FieldConst Centi
line17_sum = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Line17", Text
"Amount17"] Entry Centi
Amount}

page2Fields :: Page2 FieldConst
page2Fields :: Page2 FieldConst
page2Fields = Text -> FieldConst a -> FieldConst a
forall x. Text -> FieldConst x -> FieldConst x
within Text
"Page2" (forall {a}. FieldConst a -> FieldConst a)
-> Page2 FieldConst -> Page2 FieldConst
forall {k} (g :: (k -> *) -> *) (p :: k -> *) (q :: k -> *).
Functor g =>
(forall (a :: k). p a -> q a) -> g p -> g q
forall (p :: * -> *) (q :: * -> *).
(forall a. p a -> q a) -> Page2 p -> Page2 q
Rank2.<$> Page2 {
   $sel:line_32005_diability:Page2 :: FieldConst Bool
line_32005_diability = [Text] -> Entry Bool -> FieldConst Bool
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Enrolment", Text
"Line32005", Text
"CheckBox"] Entry Bool
Checkbox,
   $sel:line_32010_partTimeMonths:Page2 :: FieldConst Word
line_32010_partTimeMonths = [Text] -> Entry Word -> FieldConst Word
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Enrolment", Text
"Line32010", Text
"parttime_Months"] Entry Word
Count,
   $sel:line_32020_fullTimeMonths:Page2 :: FieldConst Word
line_32020_fullTimeMonths = [Text] -> Entry Word -> FieldConst Word
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Enrolment", Text
"Line32020", Text
"Fulltime_Months"] Entry Word
Count,
   $sel:line18_copy:Page2 :: FieldConst Centi
line18_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line18", Text
"Amount18"] Entry Centi
Amount,
   $sel:line19_copy:Page2 :: FieldConst Centi
line19_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line19", Text
"Amount19"] Entry Centi
Amount,
   $sel:line20_difference:Page2 :: FieldConst Centi
line20_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line20", Text
"Amount20"] Entry Centi
Amount,
   $sel:line21_copy:Page2 :: FieldConst Centi
line21_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line21", Text
"Amount21"] Entry Centi
Amount,
   $sel:line22_copy:Page2 :: FieldConst Centi
line22_copy = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line22", Text
"Amount22"] Entry Centi
Amount,
   $sel:line23_difference:Page2 :: FieldConst Centi
line23_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line23", Text
"Amount22"] Entry Centi
Amount,
   $sel:line24_transferred:Page2 :: FieldConst Centi
line24_transferred = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line24", Text
"Amount24"] Entry Centi
Amount,
   $sel:line25_difference:Page2 :: FieldConst Centi
line25_difference = [Text] -> Entry Centi -> FieldConst Centi
forall a. [Text] -> Entry a -> FieldConst a
Field [Text
"Transfer_CF", Text
"Line25", Text
"Amount25"] Entry Centi
Amount}