package verifreg

import (
	"github.com/ipfs/go-cid"
	"golang.org/x/xerrors"

	"github.com/filecoin-project/go-address"
	"github.com/filecoin-project/go-state-types/abi"

	"github.com/filecoin-project/go-state-types/cbor"
{{range .versions}}
	builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}

	"github.com/filecoin-project/lotus/chain/actors/adt"
	"github.com/filecoin-project/lotus/chain/actors/builtin"
	"github.com/filecoin-project/lotus/chain/actors"
	"github.com/filecoin-project/lotus/chain/types"
	verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg"
)

func init() {
{{range .versions}}
	builtin.RegisterActorState(builtin{{.}}.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
		return load{{.}}(store, root)
	})
{{end}}
}

var (
	Address = builtin{{.latestVersion}}.VerifiedRegistryActorAddr
	Methods = builtin{{.latestVersion}}.MethodsVerifiedRegistry
)

func Load(store adt.Store, act *types.Actor) (State, error) {
	switch act.Code {
{{range .versions}}
	case builtin{{.}}.VerifiedRegistryActorCodeID:
		return load{{.}}(store, act.Head)
{{end}}
	}
	return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}

func MakeState(store adt.Store, av actors.Version, rootKeyAddress address.Address) (State, error) {
	switch av {
{{range .versions}}
	case actors.Version{{.}}:
		return make{{.}}(store, rootKeyAddress)
{{end}}
}
	return nil, xerrors.Errorf("unknown actor version %d", av)
}

func GetActorCodeID(av actors.Version) (cid.Cid, error) {
	switch av {
{{range .versions}}
	case actors.Version{{.}}:
		return builtin{{.}}.VerifiedRegistryActorCodeID, nil
{{end}}
	}

	return cid.Undef, xerrors.Errorf("unknown actor version %d", av)
}

type RemoveDataCapProposal = verifreg{{.latestVersion}}.RemoveDataCapProposal
type RemoveDataCapRequest = verifreg{{.latestVersion}}.RemoveDataCapRequest
type RemoveDataCapParams = verifreg{{.latestVersion}}.RemoveDataCapParams
type RmDcProposalID = verifreg{{.latestVersion}}.RmDcProposalID
const SignatureDomainSeparation_RemoveDataCap = verifreg{{.latestVersion}}.SignatureDomainSeparation_RemoveDataCap

type State interface {
	cbor.Marshaler

	RootKey() (address.Address, error)
	VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error)
	VerifierDataCap(address.Address) (bool, abi.StoragePower, error)
	RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error)
	ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error
	ForEachClient(func(addr address.Address, dcap abi.StoragePower) error) error
	GetState() interface{}
}
