module Michelson.Printer
  ( RenderDoc(..)
  , printDoc
  , printUntypedContract
  , printTypedContract
  , printTypedFullContract
  , printSomeContract
  , printTypedValue
  ) where

import Data.Constraint (withDict)
import Data.Singletons (SingI)
import qualified Data.Text.Lazy as TL

import Michelson.Printer.Util (RenderDoc(..), doesntNeedParens, printDoc)
import Michelson.TypeCheck.Types (SomeContract(..))
import qualified Michelson.Typed as T
import qualified Michelson.Untyped as U

-- | Convert an untyped contract into a textual representation which
-- will be accepted by the OCaml reference client.
printUntypedContract :: (RenderDoc op) => Bool -> U.Contract' op -> TL.Text
printUntypedContract forceSingleLine = printDoc forceSingleLine . renderDoc doesntNeedParens

-- | Convert a typed contract into a textual representation which
-- will be accepted by the OCaml reference client.
printTypedContract :: (SingI p, SingI s) => Bool -> T.Contract p s -> TL.Text
printTypedContract forceSingleLine =
  printUntypedContract forceSingleLine . T.convertContract

printTypedFullContract :: Bool -> T.FullContract p s -> TL.Text
printTypedFullContract forceSingleLine fc@T.FullContract{} =
  printUntypedContract forceSingleLine $ T.convertFullContract fc

printTypedValue
  :: forall t.
      (T.ProperPrintedValBetterErrors t)
  => Bool -> T.Value t -> TL.Text
printTypedValue forceSingleLine =
  withDict (T.properPrintedValEvi @t) $
  printDoc forceSingleLine . renderDoc doesntNeedParens . T.untypeValue

printSomeContract :: Bool -> SomeContract -> TL.Text
printSomeContract forceSingleLine (SomeContract fc) =
  printTypedFullContract forceSingleLine fc