// Code generated by "requestgen -method GET -url /v1/cryptocurrency/listings/historical -type ListingsHistoricalRequest -responseType Response -responseDataField Data -responseDataType []Data"; DO NOT EDIT.

package v1

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
	"reflect"
	"regexp"
)

func (l *ListingsHistoricalRequest) SetDate(Date string) *ListingsHistoricalRequest {
	l.Date = Date
	return l
}

func (l *ListingsHistoricalRequest) SetStart(Start int) *ListingsHistoricalRequest {
	l.Start = &Start
	return l
}

func (l *ListingsHistoricalRequest) SetLimit(Limit int) *ListingsHistoricalRequest {
	l.Limit = &Limit
	return l
}

func (l *ListingsHistoricalRequest) SetConvert(Convert string) *ListingsHistoricalRequest {
	l.Convert = &Convert
	return l
}

func (l *ListingsHistoricalRequest) SetConvertID(ConvertID string) *ListingsHistoricalRequest {
	l.ConvertID = &ConvertID
	return l
}

func (l *ListingsHistoricalRequest) SetSort(Sort string) *ListingsHistoricalRequest {
	l.Sort = &Sort
	return l
}

func (l *ListingsHistoricalRequest) SetSortDir(SortDir string) *ListingsHistoricalRequest {
	l.SortDir = &SortDir
	return l
}

func (l *ListingsHistoricalRequest) SetCryptocurrencyType(CryptocurrencyType string) *ListingsHistoricalRequest {
	l.CryptocurrencyType = &CryptocurrencyType
	return l
}

func (l *ListingsHistoricalRequest) SetAux(Aux string) *ListingsHistoricalRequest {
	l.Aux = &Aux
	return l
}

// GetQueryParameters builds and checks the query parameters and returns url.Values
func (l *ListingsHistoricalRequest) GetQueryParameters() (url.Values, error) {
	var params = map[string]interface{}{}
	// check Date field -> json key date
	Date := l.Date

	// TEMPLATE check-required
	if len(Date) == 0 {
		return nil, fmt.Errorf("date is required, empty string given")
	}
	// END TEMPLATE check-required

	// assign parameter of Date
	params["date"] = Date
	// check Start field -> json key start
	if l.Start != nil {
		Start := *l.Start

		// assign parameter of Start
		params["start"] = Start
	} else {
		Start := 1

		// assign parameter of Start
		params["start"] = Start
	}
	// check Limit field -> json key limit
	if l.Limit != nil {
		Limit := *l.Limit

		// assign parameter of Limit
		params["limit"] = Limit
	} else {
		Limit := 100

		// assign parameter of Limit
		params["limit"] = Limit
	}
	// check Convert field -> json key convert
	if l.Convert != nil {
		Convert := *l.Convert

		// assign parameter of Convert
		params["convert"] = Convert
	} else {
	}
	// check ConvertID field -> json key convert_id
	if l.ConvertID != nil {
		ConvertID := *l.ConvertID

		// assign parameter of ConvertID
		params["convert_id"] = ConvertID
	} else {
	}
	// check Sort field -> json key sort
	if l.Sort != nil {
		Sort := *l.Sort

		// TEMPLATE check-valid-values
		switch Sort {
		case "cmc_rank", "name", "symbol", "market_cap", "price", "circulating_supply", "total_supply", "max_supply", "num_market_pairs", "volume_24h", "percent_change_1h", "percent_change_24h", "percent_change_7d":
			params["sort"] = Sort

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

		}
		// END TEMPLATE check-valid-values

		// assign parameter of Sort
		params["sort"] = Sort
	} else {
		Sort := "cmc_rank"

		// assign parameter of Sort
		params["sort"] = Sort
	}
	// check SortDir field -> json key sort_dir
	if l.SortDir != nil {
		SortDir := *l.SortDir

		// TEMPLATE check-valid-values
		switch SortDir {
		case "asc", "desc":
			params["sort_dir"] = SortDir

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

		}
		// END TEMPLATE check-valid-values

		// assign parameter of SortDir
		params["sort_dir"] = SortDir
	} else {
	}
	// check CryptocurrencyType field -> json key cryptocurrency_type
	if l.CryptocurrencyType != nil {
		CryptocurrencyType := *l.CryptocurrencyType

		// TEMPLATE check-valid-values
		switch CryptocurrencyType {
		case "all", "coins", "tokens":
			params["cryptocurrency_type"] = CryptocurrencyType

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

		}
		// END TEMPLATE check-valid-values

		// assign parameter of CryptocurrencyType
		params["cryptocurrency_type"] = CryptocurrencyType
	} else {
		CryptocurrencyType := "all"

		// assign parameter of CryptocurrencyType
		params["cryptocurrency_type"] = CryptocurrencyType
	}
	// check Aux field -> json key aux
	if l.Aux != nil {
		Aux := *l.Aux

		// assign parameter of Aux
		params["aux"] = Aux
	} else {
		Aux := "platform,tags,date_added,circulating_supply,total_supply,max_supply,cmc_rank,num_market_pairs"

		// assign parameter of Aux
		params["aux"] = Aux
	}

	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 (l *ListingsHistoricalRequest) GetParameters() (map[string]interface{}, error) {
	var params = map[string]interface{}{}

	return params, nil
}

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

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

	for _k, _v := range params {
		if l.isVarSlice(_v) {
			l.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 (l *ListingsHistoricalRequest) GetParametersJSON() ([]byte, error) {
	params, err := l.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 (l *ListingsHistoricalRequest) GetSlugParameters() (map[string]interface{}, error) {
	var params = map[string]interface{}{}

	return params, nil
}

func (l *ListingsHistoricalRequest) 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 (l *ListingsHistoricalRequest) 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 (l *ListingsHistoricalRequest) isVarSlice(_v interface{}) bool {
	rt := reflect.TypeOf(_v)
	switch rt.Kind() {
	case reflect.Slice:
		return true
	}
	return false
}

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

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

	return slugs, nil
}

func (l *ListingsHistoricalRequest) Do(ctx context.Context) ([]Data, error) {

	// no body params
	var params interface{}
	query, err := l.GetQueryParameters()
	if err != nil {
		return nil, err
	}

	apiURL := "/v1/cryptocurrency/listings/historical"

	req, err := l.Client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
	if err != nil {
		return nil, err
	}

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

	var apiResponse Response
	if err := response.DecodeJSON(&apiResponse); err != nil {
		return nil, err
	}
	var data []Data
	if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
		return nil, err
	}
	return data, nil
}
