{-# OPTIONS --safe #-}

open import Data.Nat.Properties using (+-0-monoid)
open import Data.Rational using ()

open import Ledger.Prelude
open import Ledger.Dijkstra.Specification.Gov.Base
open import Ledger.Core.Specification.ProtocolVersion

module Ledger.Dijkstra.Specification.Enact (gs : _) (open GovStructure gs) where

open import Ledger.Dijkstra.Specification.Gov.Actions gs


record EnactEnv : Type where
  field
    gid       : GovActionID
    treasury  : Treasury
    epoch     : Epoch

-- EnactState is modified only by enacting governance action
-- All fields contain a GovActionID since they are hash-protected.
record EnactState : Type where
  field
    cc            : HashProtected (Maybe ((Credential  Epoch) × ))
    constitution  : HashProtected (DocHash × Maybe ScriptHash)
    pv            : HashProtected ProtVer
    pparams       : HashProtected PParams
    withdrawals   : Withdrawals


record HasEnactState {a} (A : Type a) : Type a where
  field EnactStateOf : A  EnactState
open HasEnactState ⦃...⦄ public

instance
  HasPParams-EnactState : HasPParams EnactState
  HasPParams-EnactState .PParamsOf = proj₁  EnactState.pparams

  HasccMaxTermLength-EnactState : HasCCMaxTermLength EnactState
  HasccMaxTermLength-EnactState .CCMaxTermLengthOf = PParams.ccMaxTermLength  PParamsOf

  HasWithdrawals-EnactState : HasWithdrawals EnactState
  HasWithdrawals-EnactState .WithdrawalsOf = EnactState.withdrawals

  unquoteDecl HasCast-EnactEnv = derive-HasCast
    [ (quote EnactEnv , HasCast-EnactEnv) ]

open EnactState


ccCreds : HashProtected (Maybe ((Credential  Epoch) × ))   Credential
ccCreds (just x   , _)  = dom (x .proj₁)
ccCreds (nothing  , _)  = 

getHash :  {a}  NeedsHash a  Maybe GovActionID
getHash {NoConfidence}        h = just h
getHash {UpdateCommittee}     h = just h
getHash {NewConstitution}     h = just h
getHash {TriggerHardFork}     h = just h
getHash {ChangePParams}       h = just h
getHash {TreasuryWithdrawal}  _ = nothing
getHash {Info}                _ = nothing

getHashES : EnactState  GovActionType  Maybe GovActionID
getHashES es NoConfidence          = just (es .cc .proj₂)
getHashES es (UpdateCommittee)     = just (es .cc .proj₂)
getHashES es (NewConstitution)     = just (es .constitution .proj₂)
getHashES es (TriggerHardFork)     = just (es .pv .proj₂)
getHashES es (ChangePParams)       = just (es .pparams .proj₂)
getHashES es (TreasuryWithdrawal)  = nothing
getHashES es Info                  = nothing


private variable
  s        : EnactState
  up       : PParamsUpdate
  new      : Credential  Epoch
  removed  :  Credential
  q        : 
  dHash    : DocHash
  sHash    : Maybe ScriptHash
  protVer  : ProtVer
  wdrls    : Withdrawals
  t        : Treasury
  gid      : GovActionID
  ep       : Epoch

instance
  _ = +-0-monoid


data _⊢_⇀⦇_,ENACT⦈_ : EnactEnv  EnactState  GovAction  EnactState  Type where

  Enact-NoConf :
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{2977}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{2983}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{2987}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#625}{\htmlId{3001}{\htmlClass{InductiveConstructor}{\text{NoConfidence}}}}\, \\ \,\htmlId{3016}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$ ,ENACT⦈ record s { cc = nothing , gid }

  Enact-UpdComm : let old      = maybe proj₁  (s .cc .proj₁)
                      maxTerm  = CCMaxTermLengthOf s +ᵉ ep
                  in
    ∀[ term  range new ] term  maxTerm
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{3296}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{3302}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{3306}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#663}{\htmlId{3320}{\htmlClass{InductiveConstructor}{\text{UpdateCommittee}}}}\, \\ \,\htmlId{3338}{\htmlClass{Symbol}{\text{(}}}\,\,\href{Ledger.Dijkstra.Specification.Enact.html#2564}{\htmlId{3339}{\htmlClass{Generalizable}{\text{new}}}}\, , \,\href{Ledger.Dijkstra.Specification.Enact.html#2596}{\htmlId{3345}{\htmlClass{Generalizable}{\text{removed}}}}\, , \,\href{Ledger.Dijkstra.Specification.Enact.html#2622}{\htmlId{3355}{\htmlClass{Generalizable}{\text{q}}}}\,\,\htmlId{3356}{\htmlClass{Symbol}{\text{)}}}\, \end{pmatrix}$ ,ENACT⦈
      record s { cc = just ((new ∪ˡ old)  removed  , q) , gid }

  Enact-NewConst :
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{3506}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{3512}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{3516}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#701}{\htmlId{3530}{\htmlClass{InductiveConstructor}{\text{NewConstitution}}}}\, \\ \,\htmlId{3548}{\htmlClass{Symbol}{\text{(}}}\,\,\href{Ledger.Dijkstra.Specification.Enact.html#2637}{\htmlId{3549}{\htmlClass{Generalizable}{\text{dHash}}}}\, , \,\href{Ledger.Dijkstra.Specification.Enact.html#2658}{\htmlId{3557}{\htmlClass{Generalizable}{\text{sHash}}}}\,\,\htmlId{3562}{\htmlClass{Symbol}{\text{)}}}\, \end{pmatrix}$ ,ENACT⦈ record s { constitution = (dHash , sHash) , gid }

  Enact-HF :
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{3690}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{3696}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{3700}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#739}{\htmlId{3714}{\htmlClass{InductiveConstructor}{\text{TriggerHardFork}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2688}{\htmlId{3732}{\htmlClass{Generalizable}{\text{protVer}}}}\, \end{pmatrix}$ ,ENACT⦈ record s { pv = protVer , gid }

  Enact-PParams :
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{3853}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{3859}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{3863}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#777}{\htmlId{3877}{\htmlClass{InductiveConstructor}{\text{ChangePParams}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2537}{\htmlId{3893}{\htmlClass{Generalizable}{\text{up}}}}\, \end{pmatrix}$ ,ENACT⦈
      record s { pparams = applyUpdate (PParamsOf s) up , gid }

  Enact-Wdrl : let newWdrls = s .withdrawals ∪⁺ wdrls in
    ∑[ x  newWdrls ] x  t
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{4108}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{4114}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{4118}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#815}{\htmlId{4132}{\htmlClass{InductiveConstructor}{\text{TreasuryWithdrawal}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2709}{\htmlId{4153}{\htmlClass{Generalizable}{\text{wdrls}}}}\, \end{pmatrix}$ ,ENACT⦈ record s { withdrawals = newWdrls }

  Enact-Info :
    ───────────────────────────────────────
    $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Enact.html#2756}{\htmlId{4273}{\htmlClass{Generalizable}{\text{gid}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2734}{\htmlId{4279}{\htmlClass{Generalizable}{\text{t}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Enact.html#2781}{\htmlId{4283}{\htmlClass{Generalizable}{\text{ep}}}}\, \end{pmatrix}$  s ⇀⦇ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#853}{\htmlId{4297}{\htmlClass{InductiveConstructor}{\text{Info}}}}\, \\ \,\htmlId{4304}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$ ,ENACT⦈ s