{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeApplications           #-}
{-# LANGUAGE TypeOperators              #-}
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}

module Main (main) where

import           Composite
import           Composite.CoRecord         hiding (Op)
import           Composite.Dhall
import           Composite.Dhall.CoRecord   ()
import           Composite.TH
import           Data.Functor.Contravariant
import           Data.Functor.Identity
import           Data.Text
import           Dhall                      as D hiding (field)
import           Test.Tasty
import           Test.Tasty.HUnit

withLensesAndProxies
  [d|
    type A = "a" :-> Text

    type B = "b" :-> Int
    |]

type RecId = Record '[A, B]

type CoRecId = CoRec Identity '[A, B]

type RecMaybe = Rec Maybe '[A, B]

type RecList = Rec [] '[A, B]

recId :: RecId
recId = "foo" :*: 5 :*: RNil

coRecId :: CoRecId
coRecId = field @A "foo"

coRecId2 :: CoRecId
coRecId2 = field @B 5

recMaybe :: RecMaybe
recMaybe = Just "foo" :^: Just 5 :^: RNil

recList :: RecList
recList = ["foo", "bar"] :^: [5, 4] :^: RNil

newtype Templates = Templates {unTemplates :: Rec TextTemplate '[A, B]}
  deriving (FromDhall) via (Rec (Op Text) '[A, B])

tests :: TestTree
tests =
  testGroup
    "Parsing Tests"
    [ testCase "parses Record" $ do
        x <- input auto "./test/data/A.dhall"
        assertEqual "" recId x,
      testCase "parses Maybe Rec" $ do
        x <- input auto "./test/data/B.dhall"
        assertEqual "" recMaybe x,
      testCase "parses Contravariant" $ do
        (_ :: Templates) <- input auto "./test/data/C.dhall"
        pure (),
      testCase "parses List Rec" $ do
        x <- input auto "./test/data/D.dhall"
        assertEqual "" recList x,
      testCase "parses CoRec" $ do
        x <- input auto "./test/data/E.dhall"
        assertEqual "" coRecId x
        y <- input auto "./test/data/F.dhall"
        assertEqual "" coRecId2 y
    ]

main :: IO ()
main = defaultMain tests