-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

-- | Allows specifying entrypoints without declaring 'ParameterHasEntrypoints'
-- instance.
module Lorentz.Entrypoints.Manual
  ( ParameterWrapper (..)
  ) where

import Lorentz.Constraints
import Lorentz.Entrypoints.Core
import Lorentz.Wrappable
import Morley.AsRPC (HasRPCRepr(..))
import Morley.Michelson.Typed

-- | Wrap parameter into this to locally assign a way to derive entrypoints for
-- it.
newtype ParameterWrapper (deriv :: Type) cp = ParameterWrapper { forall deriv cp. ParameterWrapper deriv cp -> cp
unParameterWraper :: cp }
  deriving stock (forall x.
 ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x)
-> (forall x.
    Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp)
-> Generic (ParameterWrapper deriv cp)
forall x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
forall x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall deriv cp x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
forall deriv cp x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
$cto :: forall deriv cp x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
$cfrom :: forall deriv cp x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
Generic
  deriving anyclass (WellTypedToT (ParameterWrapper deriv cp)
WellTypedToT (ParameterWrapper deriv cp)
-> (ParameterWrapper deriv cp
    -> Value (ToT (ParameterWrapper deriv cp)))
-> (Value (ToT (ParameterWrapper deriv cp))
    -> ParameterWrapper deriv cp)
-> IsoValue (ParameterWrapper deriv cp)
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
forall a.
WellTypedToT a
-> (a -> Value (ToT a)) -> (Value (ToT a) -> a) -> IsoValue a
forall {deriv} {cp}.
IsoValue cp =>
WellTypedToT (ParameterWrapper deriv cp)
forall deriv cp.
IsoValue cp =>
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
forall deriv cp.
IsoValue cp =>
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
fromVal :: Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
$cfromVal :: forall deriv cp.
IsoValue cp =>
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
toVal :: ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
$ctoVal :: forall deriv cp.
IsoValue cp =>
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
IsoValue, ToT (ParameterWrapper deriv cp)
~ ToT (Unwrappabled (ParameterWrapper deriv cp))
(ToT (ParameterWrapper deriv cp)
 ~ ToT (Unwrappabled (ParameterWrapper deriv cp)))
-> Unwrappable (ParameterWrapper deriv cp)
forall s. (ToT s ~ ToT (Unwrappabled s)) -> Unwrappable s
forall {deriv} {cp}.
ToT (ParameterWrapper deriv cp)
~ ToT (Unwrappabled (ParameterWrapper deriv cp))
Unwrappable, Unwrappable (ParameterWrapper deriv cp)
Unwrappable (ParameterWrapper deriv cp)
-> Wrappable (ParameterWrapper deriv cp)
forall s. Unwrappable s -> Wrappable s
forall deriv cp. Unwrappable (ParameterWrapper deriv cp)
Wrappable)

instance HasRPCRepr cp => HasRPCRepr (ParameterWrapper deriv cp) where
  type AsRPC (ParameterWrapper deriv cp) = ParameterWrapper deriv (AsRPC cp)

-- Helper for implementing @instance ParameterHasEntrypoints ParameterWrapper@.
data PwDeriv deriv
instance EntrypointsDerivation deriv cp =>
         EntrypointsDerivation (PwDeriv deriv) (ParameterWrapper deriv cp) where
  type EpdAllEntrypoints (PwDeriv deriv) (ParameterWrapper deriv cp) =
    EpdAllEntrypoints deriv cp
  type EpdLookupEntrypoint (PwDeriv deriv) (ParameterWrapper deriv cp) =
    EpdLookupEntrypoint deriv cp
  epdNotes :: (Notes (ToT (ParameterWrapper deriv cp)), RootAnn)
epdNotes = forall {k} (deriv :: k) cp.
EntrypointsDerivation deriv cp =>
(Notes (ToT cp), RootAnn)
forall deriv cp.
EntrypointsDerivation deriv cp =>
(Notes (ToT cp), RootAnn)
epdNotes @deriv @cp
  epdCall :: forall (name :: Symbol).
ParameterScope (ToT (ParameterWrapper deriv cp)) =>
Label name
-> EpConstructionRes
     (ToT (ParameterWrapper deriv cp))
     (Eval
        (EpdLookupEntrypoint
           (PwDeriv deriv) (ParameterWrapper deriv cp) name))
epdCall = forall {k} (deriv :: k) cp (name :: Symbol).
(EntrypointsDerivation deriv cp, ParameterScope (ToT cp)) =>
Label name
-> EpConstructionRes
     (ToT cp) (Eval (EpdLookupEntrypoint deriv cp name))
forall deriv cp (name :: Symbol).
(EntrypointsDerivation deriv cp, ParameterScope (ToT cp)) =>
Label name
-> EpConstructionRes
     (ToT cp) (Eval (EpdLookupEntrypoint deriv cp name))
epdCall @deriv @cp
  epdDescs :: Rec
  EpCallingDesc
  (EpdAllEntrypoints (PwDeriv deriv) (ParameterWrapper deriv cp))
epdDescs = forall {k} (deriv :: k) cp.
EntrypointsDerivation deriv cp =>
Rec EpCallingDesc (EpdAllEntrypoints deriv cp)
forall deriv cp.
EntrypointsDerivation deriv cp =>
Rec EpCallingDesc (EpdAllEntrypoints deriv cp)
epdDescs @deriv @cp

instance ( NiceParameter cp
         , EntrypointsDerivation epd cp
         , RequireAllUniqueEntrypoints' epd cp
         ) =>
         ParameterHasEntrypoints (ParameterWrapper epd cp) where
  type ParameterEntrypointsDerivation (ParameterWrapper epd cp) = PwDeriv epd