-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ

module Test.Code.Decomposition
  ( Meta (..)
  , Color
  , Storage (..)
  , setDecomposedVariable
  , setMaterializedVariable
  , setDecomposedField
  ) where

import Indigo

data Meta = Meta
  { mWeight :: Integer
  , mDescr  :: MText
  } deriving stock (Generic, Show)
    deriving anyclass (IsoValue, HasAnnotation)

data Color = Blue | White | Red
  deriving stock (Generic, Show, Enum, Bounded)
  deriving anyclass (IsoValue, HasAnnotation)

data Storage = Storage
  { sColor :: Color
  , sX :: Integer
  , sY :: Integer
  , sMeta :: Meta
  } deriving stock (Generic, Show)
    deriving anyclass (IsoValue, HasAnnotation)

instance HasField Meta "weight" Integer where
  fieldLens = fieldLensADT #mWeight

instance HasField Meta "descr" MText where
  fieldLens = fieldLensADT #mDescr

instance HasField Storage "color" Color where
  fieldLens = fieldLensADT #sColor

instance HasField Storage "x" Integer where
  fieldLens = fieldLensADT #sX

instance HasField Storage "y" Integer where
  fieldLens = fieldLensADT #sY

instance HasField Storage "weight" Integer where
  fieldLens = fieldLensDeeper #sMeta

instance HasField Storage "descr" MText where
  fieldLens = fieldLensDeeper #sMeta

setDecomposedVariable :: ContractCode (Color, (Integer, Integer)) Storage
setDecomposedVariable = compileIndigoContract $ \param -> do
  let storage = storageVar @Storage
  let newStorageVal =
        storage !! (#x, fst (snd param))
                !! (#y, snd (snd param))
                !! (#color, fst param)
                !! (#weight, 0 int)
  storage =: newStorageVal

setMaterializedVariable :: ContractCode (Color, (Integer, Integer)) Storage
setMaterializedVariable = compileIndigoContract $ \param -> do
  let storage = storageVar @Storage
  let newStorageVal =
        construct
        ( fst param
        , fst (snd param)
        , snd (snd param)
        , construct ( constExpr (0 int)
                    , constExpr [mt|"hello, Ivan!"|]
                    )
        )
  storage =: newStorageVal

setDecomposedField :: ContractCode (Color, Integer) Storage
setDecomposedField = compileIndigoContract $ \param -> do
  let storage = storageVar @Storage
  setField storage #color (fst param)
  setField storage #weight (snd param)
