// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package config

import (
	"encoding/json"
	"time"

	"github.com/luxfi/constants"
	"github.com/luxfi/ids"
	"github.com/luxfi/math/set"
	"github.com/luxfi/node/chains"
)

var Default = Config{
	Network:                       DefaultNetwork,
	BlockCacheSize:                64 * constants.MiB,
	TxCacheSize:                   128 * constants.MiB,
	TransformedNetTxCacheSize:     4 * constants.MiB,
	RewardUTXOsCacheSize:          2048,
	ChainCacheSize:                2048,
	ChainDBCacheSize:              2048,
	BlockIDCacheSize:              8192,
	FxOwnerCacheSize:              4 * constants.MiB,
	NetToL1ConversionCacheSize:    4 * constants.MiB,
	L1WeightsCacheSize:            16 * constants.KiB,
	L1InactiveValidatorsCacheSize: 256 * constants.KiB,
	L1ChainIDNodeIDCacheSize:        16 * constants.KiB,
	ChecksumsEnabled:              false,
	MempoolPruneFrequency:         30 * time.Minute,
	TxFee:                         constants.MilliLux,
	CreateAssetTxFee:              constants.MilliLux,
	CreateNetworkTxFee:            constants.Lux,
	CreateChainTxFee:              constants.Lux,
	AddNetworkValidatorFee:        0,
	AddNetworkDelegatorFee:        0,
}

// Config contains all of the user-configurable parameters of the PlatformVM.
type Config struct {
	Network                       Network         `json:"network"`
	BlockCacheSize                int             `json:"block-cache-size"`
	TxCacheSize                   int             `json:"tx-cache-size"`
	TransformedNetTxCacheSize     int             `json:"transformed-chain-tx-cache-size"`
	RewardUTXOsCacheSize          int             `json:"reward-utxos-cache-size"`
	ChainCacheSize                int             `json:"chain-cache-size"`
	ChainDBCacheSize              int             `json:"chain-db-cache-size"`
	BlockIDCacheSize              int             `json:"block-id-cache-size"`
	FxOwnerCacheSize              int             `json:"fx-owner-cache-size"`
	NetToL1ConversionCacheSize    int             `json:"chain-to-l1-conversion-cache-size"`
	L1WeightsCacheSize            int             `json:"l1-weights-cache-size"`
	L1InactiveValidatorsCacheSize int             `json:"l1-inactive-validators-cache-size"`
	L1ChainIDNodeIDCacheSize      int             `json:"l1-chain-id-node-id-cache-size"`
	ChecksumsEnabled              bool            `json:"checksums-enabled"`
	MempoolPruneFrequency         time.Duration   `json:"mempool-prune-frequency"`
	SybilProtectionEnabled        bool            `json:"sybil-protection-enabled"`
	TrackedChains                 set.Set[ids.ID] `json:"tracked-chains"`
	Chains                        chains.Manager  `json:"-"`

	// Transaction fees
	TxFee                         uint64 `json:"tx-fee"`
	CreateAssetTxFee              uint64 `json:"create-asset-tx-fee"`
	CreateNetworkTxFee            uint64 `json:"create-network-tx-fee"`
	CreateChainTxFee              uint64 `json:"create-chain-tx-fee"`
	AddNetworkValidatorFee        uint64 `json:"add-network-validator-fee"`
	AddNetworkDelegatorFee        uint64 `json:"add-network-delegator-fee"`
}

// GetConfig returns a Config from the provided json encoded bytes. If a
// configuration is not provided in the bytes, the default value is set. If
// empty bytes are provided, the default config is returned.
func GetConfig(b []byte) (*Config, error) {
	ec := Default

	// An empty slice is invalid json, so handle that as a special case.
	if len(b) == 0 {
		return &ec, nil
	}

	return &ec, json.Unmarshal(b, &ec)
}
