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

module Tax.Canada.Province.ON.ON428.Types where

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

import Tax.Canada.Shared (BaseCredit, MedicalExpenses, SubCalculation, TaxIncomeBracket)

data ON428 line = ON428 {
   forall (line :: * -> *). ON428 line -> Page1 line
page1 :: Page1 line,
   forall (line :: * -> *). ON428 line -> Page2 line
page2 :: Page2 line,
   forall (line :: * -> *). ON428 line -> Page3 line
page3 :: Page3 line,
   forall (line :: * -> *). ON428 line -> Page4 line
page4 :: Page4 line}

data Page1 line = Page1 {
   forall (line :: * -> *). Page1 line -> line Centi
line1 :: line Centi,
   forall (line :: * -> *). Page1 line -> Page1PartA line
partA :: Page1PartA line,
   forall (line :: * -> *). Page1 line -> Page1PartB line
partB :: Page1PartB line}

data Page1PartA line = Page1PartA {
   forall (line :: * -> *). Page1PartA line -> TaxIncomeBracket line
column1 :: TaxIncomeBracket line,
   forall (line :: * -> *). Page1PartA line -> TaxIncomeBracket line
column2 :: TaxIncomeBracket line,
   forall (line :: * -> *). Page1PartA line -> TaxIncomeBracket line
column3 :: TaxIncomeBracket line,
   forall (line :: * -> *). Page1PartA line -> TaxIncomeBracket line
column4 :: TaxIncomeBracket line,
   forall (line :: * -> *). Page1PartA line -> TaxIncomeBracket line
column5 :: TaxIncomeBracket line}

data Page1PartB line = Page1PartB {
   forall (line :: * -> *). Page1PartB line -> line Centi
line9_basic :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line10_age :: line Centi,
   forall (line :: * -> *). Page1PartB line -> BaseCredit line
spouseAmount :: BaseCredit line,
   forall (line :: * -> *). Page1PartB line -> BaseCredit line
dependantAmount :: BaseCredit line,
   forall (line :: * -> *). Page1PartB line -> line Centi
line17_caregiver :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line18 :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line19_cppQpp :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line20_cppQpp :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line21_employmentInsurance :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line22_employmentInsurance :: line Centi,
   forall (line :: * -> *). Page1PartB line -> line Centi
line23_adoption :: line Centi,
   forall (line :: * -> *). Page1PartB line -> SubCalculation line
line24_sum :: SubCalculation line,
   forall (line :: * -> *). Page1PartB line -> line Centi
line25 :: line Centi}

data Page2 line = Page2 {
  forall (line :: * -> *). Page2 line -> Page2PartB line
partB :: Page2PartB line,
  forall (line :: * -> *). Page2 line -> Page2PartC line
partC :: Page2PartC line}

data Page2PartB line = Page2PartB {
   forall (line :: * -> *). Page2PartB line -> line Centi
line26 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line27_pension :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line28 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line29_disability :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line30 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line31 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line32_interest :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line33_education :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line34_transferred :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Centi
line35 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> MedicalExpenses line
medicalExpenses :: MedicalExpenses line,
   forall (line :: * -> *). Page2PartB line -> line Centi
line42 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> SubCalculation line
line43_sum :: SubCalculation line,
   forall (line :: * -> *). Page2PartB line -> line Centi
line44 :: line Centi,
   forall (line :: * -> *). Page2PartB line -> line Rational
line45_rate :: line Rational,
   forall (line :: * -> *). Page2PartB line -> line Centi
line46_fraction :: line Centi,
   forall (line :: * -> *). Page2PartB line -> Donations line
donations :: Donations line,
   forall (line :: * -> *). Page2PartB line -> line Centi
line50 :: line Centi}

data Donations line = Donations {
   forall (line :: * -> *). Donations line -> line Centi
line47_base :: line Centi,
   forall (line :: * -> *). Donations line -> line Centi
line47_fraction :: line Centi,
   forall (line :: * -> *). Donations line -> line Centi
line48_base :: line Centi,
   forall (line :: * -> *). Donations line -> line Centi
line48_fraction :: line Centi,
   forall (line :: * -> *). Donations line -> SubCalculation line
line49_sum :: SubCalculation line}

data Page2PartC line = Page2PartC {
   forall (line :: * -> *). Page2PartC line -> line Centi
line51_tax :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line52_credits :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line53 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line54 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line55 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line56 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line57 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line58 :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line59_copy :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line59_product :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line60_lesser :: line Centi,
   forall (line :: * -> *). Page2PartC line -> line Centi
line61 :: line Centi}

data Page3 line = Page3 {
   forall (line :: * -> *). Page3 line -> line Centi
line62 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line63 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line64 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line65 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line66_copy :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line66_surtax :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line67_copy :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line67_surtax :: line Centi,
   forall (line :: * -> *). Page3 line -> SubCalculation line
line68_sum :: SubCalculation line,
   forall (line :: * -> *). Page3 line -> line Centi
line69 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line70 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line71 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line72 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line73 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line74_basicReduction :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line75_amount :: line Centi,
   forall (line :: * -> *). Page3 line -> line Word
line75_childrenNum :: line Word,
   forall (line :: * -> *). Page3 line -> line Centi
line76_amount :: line Centi,
   forall (line :: * -> *). Page3 line -> line Word
line76_childrenNum :: line Word,
   forall (line :: * -> *). Page3 line -> line Centi
line77 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line78_copy :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line78_product :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line79 :: line Centi,
   forall (line :: * -> *). Page3 line -> SubCalculation line
line80_difference :: SubCalculation line,
   forall (line :: * -> *). Page3 line -> line Centi
line81 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line82 :: line Centi,
   forall (line :: * -> *). Page3 line -> line Centi
line83 :: line Centi}

data Page4 line = Page4 {
   forall (line :: * -> *). Page4 line -> line Centi
line84 :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line85_lift :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line86 :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line87_foodDonations :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line87_fraction :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line88 :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line89_health :: line Centi,
   forall (line :: * -> *). Page4 line -> line Centi
line90 :: line Centi,
   forall (line :: * -> *). Page4 line -> HealthPremium line
healthPremium :: HealthPremium line}

data HealthPremium line = HealthPremium {
   forall (line :: * -> *).
HealthPremium line -> HealthPremiumBracket line
row1 :: HealthPremiumBracket line,
   forall (line :: * -> *).
HealthPremium line -> HealthPremiumBracket line
row2 :: HealthPremiumBracket line,
   forall (line :: * -> *).
HealthPremium line -> HealthPremiumBracket line
row3 :: HealthPremiumBracket line,
   forall (line :: * -> *).
HealthPremium line -> HealthPremiumBracket line
row4 :: HealthPremiumBracket line,
   forall (line :: * -> *).
HealthPremium line -> HealthPremiumBracket line
row5 :: HealthPremiumBracket line}

data HealthPremiumBracket line = HealthPremiumBracket {
   forall (line :: * -> *). HealthPremiumBracket line -> line Centi
taxableIncome :: line Centi,
   forall (line :: * -> *). HealthPremiumBracket line -> line Centi
overThreshold :: line Centi,
   forall (line :: * -> *). HealthPremiumBracket line -> line Centi
timesRate :: line Centi,
   forall (line :: * -> *). HealthPremiumBracket line -> line Centi
equalsTax :: line Centi}

$(foldMap
   (\t-> concat <$> sequenceA [
       [d|
           deriving instance (Show (line Centi), Show (line Rational), Show (line Word))
                          => Show ($(TH.conT t) line)
           deriving instance (Eq (line Centi), Eq (line Rational), Eq (line Word))
                          => Eq ($(TH.conT t) line)
       |],
       Rank2.TH.deriveAll t,
       Transformation.Shallow.TH.deriveAll t])
   [''ON428, ''Page1, ''Page2, ''Page3, ''Page4,
    ''Page1PartA, ''Page1PartB, ''Page2PartB, ''Page2PartC,
    ''Donations, ''HealthPremium, ''HealthPremiumBracket])