package simulation

// import (
// 	"fmt"
// 	"math/rand"
// 	"time"

// 	"github.com/cosmos/cosmos-sdk/baseapp"
// 	"github.com/cosmos/cosmos-sdk/codec"
// 	"github.com/cosmos/cosmos-sdk/simapp/helpers"
// 	sdk "github.com/cosmos/cosmos-sdk/types"
// 	"github.com/cosmos/cosmos-sdk/x/auth"
// 	"github.com/cosmos/cosmos-sdk/x/simulation"

// 	appparams "github.com/kava-labs/kava/app/params"
// 	"github.com/kava-labs/kava/x/pricefeed/keeper"
// 	"github.com/kava-labs/kava/x/pricefeed/types"
// )

// // Simulation operation weights constants
// const (
// 	OpWeightMsgUpdatePrices = "op_weight_msg_update_prices"

// 	// Block time params are un-exported constants in cosmos-sdk/x/simulation.
// 	// Copy them here in lieu of importing them.
// 	minTimePerBlock time.Duration = (10000 / 2) * time.Second
// 	maxTimePerBlock time.Duration = 10000 * time.Second

// 	// Calculate the average block time
// 	AverageBlockTime time.Duration = (maxTimePerBlock - minTimePerBlock) / 2
// )

// // WeightedOperations returns all the operations from the module with their respective weights
// func WeightedOperations(
// 	appParams simulation.AppParams, cdc *codec.Codec, ak auth.AccountKeeper, k keeper.Keeper,
// ) simulation.WeightedOperations {
// 	var weightMsgUpdatePrices int
// 	// var numBlocks int

// 	appParams.GetOrGenerate(cdc, OpWeightMsgUpdatePrices, &weightMsgUpdatePrices, nil,
// 		func(_ *rand.Rand) {
// 			weightMsgUpdatePrices = appparams.DefaultWeightMsgUpdatePrices
// 		},
// 	)

// 	return simulation.WeightedOperations{
// 		simulation.NewWeightedOperation(
// 			weightMsgUpdatePrices,
// 			SimulateMsgUpdatePrices(ak, k, 10000),
// 		),
// 	}
// }

// // SimulateMsgUpdatePrices updates the prices of various assets by randomly varying them based on current price
// func SimulateMsgUpdatePrices(ak auth.AccountKeeper, keeper keeper.Keeper, blocks int) simulation.Operation {
// 	// runs one at the start of each simulation
// 	startingPrices := map[string]sdk.Dec{
// 		"btc:usd": sdk.MustNewDecFromStr("7000"),
// 		"bnb:usd": sdk.MustNewDecFromStr("15"),
// 		"xrp:usd": sdk.MustNewDecFromStr("0.25"),
// 	}

// 	// creates the new price generator from starting prices - resets for each sim
// 	priceGenerator := NewPriceGenerator(startingPrices)

// 	return func(
// 		r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string,
// 	) (simulation.OperationMsg, []simulation.FutureOperation, error) {
// 		// walk prices to current block height, noop if already called for current height
// 		priceGenerator.Step(r, ctx.BlockHeight())

// 		randomMarket := pickRandomAsset(ctx, keeper, r)
// 		marketID := randommarket.MarketId
// 		address := getRandomOracle(r, randomMarket)

// 		oracle, found := simulation.FindAccount(accs, address)
// 		if !found {
// 			return simulation.NoOpMsg(types.ModuleName), nil, nil
// 		}

// 		oracleAcc := ak.GetAccount(ctx, oracle.Address)
// 		if oracleAcc == nil {
// 			return simulation.NoOpMsg(types.ModuleName), nil, nil
// 		}

// 		// get price for marketID and current block height set in Step
// 		price := priceGenerator.GetCurrentPrice(marketID)

// 		// get the expiry time based off the current time
// 		expiry := getExpiryTime(ctx)

// 		// now create the msg to post price
// 		msg := types.NewMsgPostPrice(oracle.Address, marketID, price, expiry)

// 		spendable := oracleAcc.SpendableCoins(ctx.BlockTime())
// 		fees, err := simulation.RandomFees(r, ctx, spendable)
// 		if err != nil {
// 			return simulation.NoOpMsg(types.ModuleName), nil, err
// 		}

// 		tx := helpers.GenTx(
// 			[]sdk.Msg{msg},
// 			fees,
// 			helpers.DefaultGenTxGas,
// 			chainID,
// 			[]uint64{oracleAcc.GetAccountNumber()},
// 			[]uint64{oracleAcc.GetSequence()},
// 			oracle.PrivKey,
// 		)

// 		_, result, err := app.Deliver(tx)
// 		if err != nil {
// 			// to aid debugging, add the stack trace to the comment field of the returned opMsg
// 			return simulation.NewOperationMsg(msg, false, fmt.Sprintf("%+v", err)), nil, err
// 		}
// 		return simulation.NewOperationMsg(msg, true, result.Log), nil, nil
// 	}
// }

// // getRandomOracle picks a random oracle from the list of oracles
// func getRandomOracle(r *rand.Rand, market types.Market) sdk.AccAddress {
// 	randomIndex := simulation.RandIntBetween(r, 0, len(market.Oracles))
// 	return market.Oracles[randomIndex]
// }

// // pickRandomAsset picks a random asset out of the assets with equal probability
// // it returns the Market which includes the base asset as one of its fields
// func pickRandomAsset(ctx sdk.Context, keeper keeper.Keeper, r *rand.Rand) (market types.Market) {
// 	// get the params
// 	params := keeper.GetParams(ctx)
// 	// now pick a random asset
// 	randomIndex := simulation.RandIntBetween(r, 0, len(params.Markets))
// 	return params.Markets[randomIndex]
// }

// // getExpiryTime gets a price expiry time by taking the current time and adding a delta to it
// func getExpiryTime(ctx sdk.Context) (t time.Time) {
// 	// need to use the blocktime from the context as the context generates random start time when running simulations
// 	return ctx.BlockTime().Add(AverageBlockTime * 5000) // if blocks were 6 seconds, the expiry would be 8 hrs
// }