/*
Package tutus provides an interface to Tutus native contract.
Tutus token is special, it's not just a regular NEP-17 contract, it also
provides access to chain-specific settings and implements committee
voting system.
*/
package tutus

import (
	"git.marketally.com/tutus-one/tutus-chain/pkg/interop"
	"git.marketally.com/tutus-one/tutus-chain/pkg/interop/contract"
	"git.marketally.com/tutus-one/tutus-chain/pkg/interop/iterator"
	"git.marketally.com/tutus-one/tutus-chain/pkg/interop/tutusinternal"
)

// AccountState contains info about a Tutus holder.
type AccountState struct {
	Balance        int
	Height         int
	VoteTo         interop.PublicKey
	LastLubPerVote int
}

// Hash represents Tutus contract hash.
const Hash = "\x88\xda\x13\x8f\xbf\x88\xbf\xc3\x50\x5d\xba\x9e\x1f\xd5\xcb\x8f\xa1\x23\x81\x7a"

// Symbol represents `symbol` method of Tutus native contract.
func Symbol() string {
	return tutusinternal.CallWithToken(Hash, "symbol", int(contract.NoneFlag)).(string)
}

// Decimals represents `decimals` method of Tutus native contract.
func Decimals() int {
	return tutusinternal.CallWithToken(Hash, "decimals", int(contract.NoneFlag)).(int)
}

// TotalSupply represents `totalSupply` method of Tutus native contract.
func TotalSupply() int {
	return tutusinternal.CallWithToken(Hash, "totalSupply", int(contract.ReadStates)).(int)
}

// BalanceOf represents `balanceOf` method of Tutus native contract.
func BalanceOf(addr interop.Hash160) int {
	return tutusinternal.CallWithToken(Hash, "balanceOf", int(contract.ReadStates), addr).(int)
}

// Transfer represents `transfer` method of Tutus native contract.
func Transfer(from, to interop.Hash160, amount int, data any) bool {
	return tutusinternal.CallWithToken(Hash, "transfer",
		int(contract.All), from, to, amount, data).(bool)
}

// GetCommittee represents `getCommittee` method of Tutus native contract.
func GetCommittee() []interop.PublicKey {
	return tutusinternal.CallWithToken(Hash, "getCommittee", int(contract.ReadStates)).([]interop.PublicKey)
}

// GetCandidates represents `getCandidates` method of Tutus native contract. It
// returns up to 256 candidates. Use GetAllCandidates in case if you need the
// whole set of candidates.
func GetCandidates() []Candidate {
	return tutusinternal.CallWithToken(Hash, "getCandidates", int(contract.ReadStates)).([]Candidate)
}

// GetAllCandidates represents `getAllCandidates` method of Tutus native contract.
// It returns Iterator over the whole set of Tutus candidates sorted by public key
// bytes. Each iterator value can be cast to Candidate. Use iterator interop
// package to work with the returned Iterator.
func GetAllCandidates() iterator.Iterator {
	return tutusinternal.CallWithToken(Hash, "getAllCandidates", int(contract.ReadStates)).(iterator.Iterator)
}

// GetCandidateVote represents `getCandidateVote` method of Tutus native contract.
// It returns -1 if the candidate hasn't been registered or voted for and the
// overall candidate votes otherwise.
func GetCandidateVote(pub interop.PublicKey) int {
	return tutusinternal.CallWithToken(Hash, "getCandidateVote", int(contract.ReadStates), pub).(int)
}

// GetNextBlockValidators represents `getNextBlockValidators` method of Tutus native contract.
func GetNextBlockValidators() []interop.PublicKey {
	return tutusinternal.CallWithToken(Hash, "getNextBlockValidators", int(contract.ReadStates)).([]interop.PublicKey)
}

// GetLubPerBlock represents `getLubPerBlock` method of Tutus native contract.
func GetLubPerBlock() int {
	return tutusinternal.CallWithToken(Hash, "getLubPerBlock", int(contract.ReadStates)).(int)
}

// SetLubPerBlock represents `setLubPerBlock` method of Tutus native contract.
func SetLubPerBlock(amount int) {
	tutusinternal.CallWithTokenNoRet(Hash, "setLubPerBlock", int(contract.States), amount)
}

// GetRegisterPrice represents `getRegisterPrice` method of Tutus native contract.
func GetRegisterPrice() int {
	return tutusinternal.CallWithToken(Hash, "getRegisterPrice", int(contract.ReadStates)).(int)
}

// SetRegisterPrice represents `setRegisterPrice` method of Tutus native contract.
func SetRegisterPrice(amount int) {
	tutusinternal.CallWithTokenNoRet(Hash, "setRegisterPrice", int(contract.States), amount)
}

// RegisterCandidate represents `registerCandidate` method of Tutus native contract.
func RegisterCandidate(pub interop.PublicKey) bool {
	return tutusinternal.CallWithToken(Hash, "registerCandidate", int(contract.States|contract.AllowNotify), pub).(bool)
}

// UnregisterCandidate represents `unregisterCandidate` method of Tutus native contract.
func UnregisterCandidate(pub interop.PublicKey) bool {
	return tutusinternal.CallWithToken(Hash, "unregisterCandidate", int(contract.States|contract.AllowNotify), pub).(bool)
}

// Vote represents `vote` method of Tutus native contract.
func Vote(addr interop.Hash160, pub interop.PublicKey) bool {
	return tutusinternal.CallWithToken(Hash, "vote", int(contract.States|contract.AllowNotify), addr, pub).(bool)
}

// UnclaimedLub represents `unclaimedLub` method of Tutus native contract.
func UnclaimedLub(addr interop.Hash160, end int) int {
	return tutusinternal.CallWithToken(Hash, "unclaimedLub", int(contract.ReadStates), addr, end).(int)
}

// GetAccountState represents `getAccountState` method of Tutus native contract.
func GetAccountState(addr interop.Hash160) *AccountState {
	return tutusinternal.CallWithToken(Hash, "getAccountState", int(contract.ReadStates), addr).(*AccountState)
}

// GetCommitteeAddress represents `getCommitteeAddress` method of Tutus native contract.
func GetCommitteeAddress() interop.Hash160 {
	return tutusinternal.CallWithToken(Hash, "getCommitteeAddress", int(contract.ReadStates)).(interop.Hash160)
}
