-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Data.Universe.Instances.Reverse.JSON
  (
  ) where

import ClassyPrelude

import Data.Aeson
import Data.Aeson.Types (Parser)

import qualified Data.HashSet as HashSet
import qualified Data.HashMap.Strict as HashMap
import Data.HashMap.Strict ((!))

import Data.Universe

import Control.Monad.Fail


instance (Eq a, Hashable a, Finite a, ToJSON b, ToJSONKey a) => ToJSON (a -> b) where
  toJSON f = toJSON $ HashMap.fromList [(k, f k) | k <- universeF]

instance (Eq a, Hashable a, Finite a, FromJSON b, FromJSONKey a) => FromJSON (a -> b) where
  parseJSON val = asObject <|> asConst
    where
      asObject = do
        vMap <- parseJSON val :: Parser (HashMap a b)
        unless (HashSet.fromMap (HashMap.map (const ()) vMap) == HashSet.fromList universeF) $
          fail "Not all required keys found"
        return (vMap !)
      asConst = const <$> parseJSON val
