// Code generated by "requestgen -method POST -url /api/v3/order/cancelReplace -type CancelReplaceSpotOrderRequest -responseType .CancelReplaceSpotOrderResponse"; DO NOT EDIT.

package binanceapi

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/adshao/go-binance/v2"
	"github.com/c9s/bbgo/pkg/types"
	"net/url"
	"reflect"
	"regexp"
)

func (c *CancelReplaceSpotOrderRequest) Symbol(symbol string) *CancelReplaceSpotOrderRequest {
	c.symbol = symbol
	return c
}

func (c *CancelReplaceSpotOrderRequest) Side(side binance.SideType) *CancelReplaceSpotOrderRequest {
	c.side = side
	return c
}

func (c *CancelReplaceSpotOrderRequest) CancelReplaceMode(cancelReplaceMode CancelReplaceModeType) *CancelReplaceSpotOrderRequest {
	c.cancelReplaceMode = cancelReplaceMode
	return c
}

func (c *CancelReplaceSpotOrderRequest) TimeInForce(timeInForce string) *CancelReplaceSpotOrderRequest {
	c.timeInForce = timeInForce
	return c
}

func (c *CancelReplaceSpotOrderRequest) Quantity(quantity string) *CancelReplaceSpotOrderRequest {
	c.quantity = quantity
	return c
}

func (c *CancelReplaceSpotOrderRequest) QuoteOrderQty(quoteOrderQty string) *CancelReplaceSpotOrderRequest {
	c.quoteOrderQty = quoteOrderQty
	return c
}

func (c *CancelReplaceSpotOrderRequest) Price(price string) *CancelReplaceSpotOrderRequest {
	c.price = price
	return c
}

func (c *CancelReplaceSpotOrderRequest) CancelNewClientOrderId(cancelNewClientOrderId string) *CancelReplaceSpotOrderRequest {
	c.cancelNewClientOrderId = cancelNewClientOrderId
	return c
}

func (c *CancelReplaceSpotOrderRequest) CancelOrigClientOrderId(cancelOrigClientOrderId string) *CancelReplaceSpotOrderRequest {
	c.cancelOrigClientOrderId = cancelOrigClientOrderId
	return c
}

func (c *CancelReplaceSpotOrderRequest) CancelOrderId(cancelOrderId int) *CancelReplaceSpotOrderRequest {
	c.cancelOrderId = cancelOrderId
	return c
}

func (c *CancelReplaceSpotOrderRequest) NewClientOrderId(newClientOrderId string) *CancelReplaceSpotOrderRequest {
	c.newClientOrderId = newClientOrderId
	return c
}

func (c *CancelReplaceSpotOrderRequest) StrategyId(strategyId int) *CancelReplaceSpotOrderRequest {
	c.strategyId = strategyId
	return c
}

func (c *CancelReplaceSpotOrderRequest) StrategyType(strategyType int) *CancelReplaceSpotOrderRequest {
	c.strategyType = strategyType
	return c
}

func (c *CancelReplaceSpotOrderRequest) StopPrice(stopPrice string) *CancelReplaceSpotOrderRequest {
	c.stopPrice = stopPrice
	return c
}

func (c *CancelReplaceSpotOrderRequest) TrailingDelta(trailingDelta int) *CancelReplaceSpotOrderRequest {
	c.trailingDelta = trailingDelta
	return c
}

func (c *CancelReplaceSpotOrderRequest) IcebergQty(icebergQty string) *CancelReplaceSpotOrderRequest {
	c.icebergQty = icebergQty
	return c
}

func (c *CancelReplaceSpotOrderRequest) NewOrderRespType(newOrderRespType OrderRespType) *CancelReplaceSpotOrderRequest {
	c.newOrderRespType = newOrderRespType
	return c
}

func (c *CancelReplaceSpotOrderRequest) RecvWindow(recvWindow int) *CancelReplaceSpotOrderRequest {
	c.recvWindow = recvWindow
	return c
}

func (c *CancelReplaceSpotOrderRequest) Timestamp(timestamp types.MillisecondTimestamp) *CancelReplaceSpotOrderRequest {
	c.timestamp = timestamp
	return c
}

// GetQueryParameters builds and checks the query parameters and returns url.Values
func (c *CancelReplaceSpotOrderRequest) GetQueryParameters() (url.Values, error) {
	var params = map[string]interface{}{}

	query := url.Values{}
	for _k, _v := range params {
		query.Add(_k, fmt.Sprintf("%v", _v))
	}

	return query, nil
}

// GetParameters builds and checks the parameters and return the result in a map object
func (c *CancelReplaceSpotOrderRequest) GetParameters() (map[string]interface{}, error) {
	var params = map[string]interface{}{}
	// check symbol field -> json key symbol
	symbol := c.symbol

	// assign parameter of symbol
	params["symbol"] = symbol
	// check side field -> json key side
	side := c.side

	// assign parameter of side
	params["side"] = side
	// check cancelReplaceMode field -> json key cancelReplaceMode
	cancelReplaceMode := c.cancelReplaceMode

	// TEMPLATE check-valid-values
	switch cancelReplaceMode {
	case StopOnFailure, AllowFailure:
		params["cancelReplaceMode"] = cancelReplaceMode

	default:
		return nil, fmt.Errorf("cancelReplaceMode value %v is invalid", cancelReplaceMode)

	}
	// END TEMPLATE check-valid-values

	// assign parameter of cancelReplaceMode
	params["cancelReplaceMode"] = cancelReplaceMode
	// check timeInForce field -> json key timeInForce
	timeInForce := c.timeInForce

	// assign parameter of timeInForce
	params["timeInForce"] = timeInForce
	// check quantity field -> json key quantity
	quantity := c.quantity

	// assign parameter of quantity
	params["quantity"] = quantity
	// check quoteOrderQty field -> json key quoteOrderQty
	quoteOrderQty := c.quoteOrderQty

	// assign parameter of quoteOrderQty
	params["quoteOrderQty"] = quoteOrderQty
	// check price field -> json key price
	price := c.price

	// assign parameter of price
	params["price"] = price
	// check cancelNewClientOrderId field -> json key cancelNewClientOrderId
	cancelNewClientOrderId := c.cancelNewClientOrderId

	// assign parameter of cancelNewClientOrderId
	params["cancelNewClientOrderId"] = cancelNewClientOrderId
	// check cancelOrigClientOrderId field -> json key cancelOrigClientOrderId
	cancelOrigClientOrderId := c.cancelOrigClientOrderId

	// assign parameter of cancelOrigClientOrderId
	params["cancelOrigClientOrderId"] = cancelOrigClientOrderId
	// check cancelOrderId field -> json key cancelOrderId
	cancelOrderId := c.cancelOrderId

	// assign parameter of cancelOrderId
	params["cancelOrderId"] = cancelOrderId
	// check newClientOrderId field -> json key newClientOrderId
	newClientOrderId := c.newClientOrderId

	// assign parameter of newClientOrderId
	params["newClientOrderId"] = newClientOrderId
	// check strategyId field -> json key strategyId
	strategyId := c.strategyId

	// assign parameter of strategyId
	params["strategyId"] = strategyId
	// check strategyType field -> json key strategyType
	strategyType := c.strategyType

	// assign parameter of strategyType
	params["strategyType"] = strategyType
	// check stopPrice field -> json key stopPrice
	stopPrice := c.stopPrice

	// assign parameter of stopPrice
	params["stopPrice"] = stopPrice
	// check trailingDelta field -> json key trailingDelta
	trailingDelta := c.trailingDelta

	// assign parameter of trailingDelta
	params["trailingDelta"] = trailingDelta
	// check icebergQty field -> json key icebergQty
	icebergQty := c.icebergQty

	// assign parameter of icebergQty
	params["icebergQty"] = icebergQty
	// check newOrderRespType field -> json key newOrderRespType
	newOrderRespType := c.newOrderRespType

	// TEMPLATE check-valid-values
	switch newOrderRespType {
	case Ack, Result, Full:
		params["newOrderRespType"] = newOrderRespType

	default:
		return nil, fmt.Errorf("newOrderRespType value %v is invalid", newOrderRespType)

	}
	// END TEMPLATE check-valid-values

	// assign parameter of newOrderRespType
	params["newOrderRespType"] = newOrderRespType
	// check recvWindow field -> json key recvWindow
	recvWindow := c.recvWindow

	// assign parameter of recvWindow
	params["recvWindow"] = recvWindow
	// check timestamp field -> json key timestamp
	timestamp := c.timestamp

	// assign parameter of timestamp
	params["timestamp"] = timestamp

	return params, nil
}

// GetParametersQuery converts the parameters from GetParameters into the url.Values format
func (c *CancelReplaceSpotOrderRequest) GetParametersQuery() (url.Values, error) {
	query := url.Values{}

	params, err := c.GetParameters()
	if err != nil {
		return query, err
	}

	for _k, _v := range params {
		if c.isVarSlice(_v) {
			c.iterateSlice(_v, func(it interface{}) {
				query.Add(_k+"[]", fmt.Sprintf("%v", it))
			})
		} else {
			query.Add(_k, fmt.Sprintf("%v", _v))
		}
	}

	return query, nil
}

// GetParametersJSON converts the parameters from GetParameters into the JSON format
func (c *CancelReplaceSpotOrderRequest) GetParametersJSON() ([]byte, error) {
	params, err := c.GetParameters()
	if err != nil {
		return nil, err
	}

	return json.Marshal(params)
}

// GetSlugParameters builds and checks the slug parameters and return the result in a map object
func (c *CancelReplaceSpotOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
	var params = map[string]interface{}{}

	return params, nil
}

func (c *CancelReplaceSpotOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
	for _k, _v := range slugs {
		needleRE := regexp.MustCompile(":" + _k + "\\b")
		url = needleRE.ReplaceAllString(url, _v)
	}

	return url
}

func (c *CancelReplaceSpotOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
	sliceValue := reflect.ValueOf(slice)
	for _i := 0; _i < sliceValue.Len(); _i++ {
		it := sliceValue.Index(_i).Interface()
		_f(it)
	}
}

func (c *CancelReplaceSpotOrderRequest) isVarSlice(_v interface{}) bool {
	rt := reflect.TypeOf(_v)
	switch rt.Kind() {
	case reflect.Slice:
		return true
	}
	return false
}

func (c *CancelReplaceSpotOrderRequest) GetSlugsMap() (map[string]string, error) {
	slugs := map[string]string{}
	params, err := c.GetSlugParameters()
	if err != nil {
		return slugs, nil
	}

	for _k, _v := range params {
		slugs[_k] = fmt.Sprintf("%v", _v)
	}

	return slugs, nil
}

func (c *CancelReplaceSpotOrderRequest) Do(ctx context.Context) (*CancelReplaceSpotOrderResponse, error) {

	params, err := c.GetParameters()
	if err != nil {
		return nil, err
	}
	query := url.Values{}

	apiURL := "/api/v3/order/cancelReplace"

	req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
	if err != nil {
		return nil, err
	}

	response, err := c.client.SendRequest(req)
	if err != nil {
		return nil, err
	}

	var apiResponse CancelReplaceSpotOrderResponse
	if err := response.DecodeJSON(&apiResponse); err != nil {
		return nil, err
	}
	return &apiResponse, nil
}
