{-# OPTIONS --safe #-}

import Data.List as L

open import Ledger.Prelude
open import Ledger.Abstract
open import Ledger.Transaction using (TransactionStructure)

module Ledger.Ledger
  (txs : _) (open TransactionStructure txs)
  (abs : AbstractFunctions txs) (open AbstractFunctions abs)
  where

open import Ledger.Enact govStructure
open import Ledger.Gov txs
open import Ledger.Utxo txs abs
open import Ledger.Utxow txs abs
open import Ledger.Certs govStructure

open Tx
open GState
open GovActionState
open EnactState using (cc)


record LEnv : Type where
  field
    slot        : Slot
    ppolicy     : Maybe ScriptHash
    pparams     : PParams
    enactState  : EnactState
    treasury    : Coin

record LState : Type where


  constructor ⟦_,_,_⟧ˡ


  field
    utxoSt     : UTxOState
    govSt      : GovState
    certState  : CertState



open CertState
open DState

instance
  unquoteDecl To-LEnv To-LState = derive-To
    ((quote LEnv , To-LEnv)  (quote LState , To-LState)  [])


txgov : TxBody  List (GovVote  GovProposal)
txgov txb = map inj₂ txprop ++ map inj₁ txvote
  where open TxBody txb

rmOrphanDRepVotes : CertState  GovState  GovState
rmOrphanDRepVotes cs govSt = L.map (map₂ go) govSt
  where
   ifDRepRegistered : Voter  Type
   ifDRepRegistered (r , c) = r  DRep  c  dom (cs .gState .dreps)

   go : GovActionState  GovActionState
   go gas = record gas { votes = filterKeys ifDRepRegistered (gas .votes) }

allColdCreds : GovState  EnactState   Credential
allColdCreds govSt es =
  ccCreds (es .cc)  concatMapˢ  (_ , st)  proposedCC (st .action)) (fromList govSt)


private variable
  Γ : LEnv
  s s' s'' : LState
  utxoSt utxoSt' : UTxOState
  govSt govSt' : GovState
  certState certState' : CertState
  tx : Tx
  slot : Slot
  ppolicy : Maybe ScriptHash
  pp : PParams
  enactState : EnactState
  treasury : Coin


data _⊢_⇀⦇_,LEDGER⦈_ : LEnv  LState  Tx  LState  Type where

  LEDGER-V :
    let  txb         = tx .body


         open TxBody txb


         rewards     = certState .dState .rewards
    in
     isValid tx  true
      slot , pp , treasury    utxoSt ⇀⦇ tx ,UTXOW⦈ utxoSt'
      epoch slot , pp , txvote , txwdrls , allColdCreds govSt enactState   certState ⇀⦇ txcerts ,CERTS⦈ certState'
      txid , epoch slot , pp , ppolicy , enactState , certState' , dom rewards   rmOrphanDRepVotes certState' govSt ⇀⦇ txgov txb ,GOVS⦈ govSt'
      ────────────────────────────────
       slot , ppolicy , pp , enactState , treasury    utxoSt , govSt , certState  ⇀⦇ tx ,LEDGER⦈  utxoSt' , govSt' , certState' 

  LEDGER-I :
     isValid tx  false
      slot , pp , treasury   utxoSt ⇀⦇ tx ,UTXOW⦈ utxoSt'
      ────────────────────────────────
       slot , ppolicy , pp , enactState , treasury    utxoSt , govSt , certState  ⇀⦇ tx ,LEDGER⦈  utxoSt' , govSt , certState 


pattern LEDGER-V⋯ w x y z = LEDGER-V (w , x , y , z)
pattern LEDGER-I⋯ y z     = LEDGER-I (y , z)


_⊢_⇀⦇_,LEDGERS⦈_ : LEnv  LState  List Tx  LState  Type
_⊢_⇀⦇_,LEDGERS⦈_ = ReflexiveTransitiveClosure {sts = _⊢_⇀⦇_,LEDGER⦈_}