package routeutils

import (
	"strconv"

	"strings"

	"bitbucket.org/nemt/nemt-portal-api/infra/errors"
	"github.com/labstack/echo"
)

// GetAndValidateIntParam gets the integer param value and validates it, returning a validation error in case it's invalid
func GetAndValidateIntParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
	IDstr := c.Param(paramName)

	if strings.TrimSpace(IDstr) == "" {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	ID, err = strconv.ParseInt(IDstr, 10, 64)
	if ID == 0 {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	return
}

// GetAndValidateIntQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
func GetAndValidateIntQueryParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
	IDstr := c.QueryParam(paramName)

	if strings.TrimSpace(IDstr) == "" {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	ID, err = strconv.ParseInt(IDstr, 10, 64)
	if ID == 0 {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	return
}

// GetAndValidateFloatParam gets the integer param value and validates it, returning a validation error in case it's invalid
func GetAndValidateFloatQueryParam(c echo.Context, paramName string, errorMessage string) (ID float64, err error) {
	IDstr := c.QueryParam(paramName)

	if strings.TrimSpace(IDstr) == "" {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	ID, err = strconv.ParseFloat(IDstr, 64)
	if ID == 0 {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	return
}

// GetAndValidateStringQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
func GetAndValidateStringQueryParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
	ID = c.QueryParam(paramName)

	if strings.TrimSpace(ID) == "" {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	return
}

// GetAndValidateStringParam gets the string param value and validates it, returning a validation error in case it's invalid
func GetAndValidateStringParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
	ID = c.Param(paramName)

	if strings.TrimSpace(ID) == "" {
		err = errors.NewValidationError(paramName, errorMessage)
	}

	return
}

// GetPagingParams gets the standard paging params from the URL, returning a validation error in case it's invalid
func GetPagingParams(c echo.Context) (page int64, quantity int64) {
	pg := c.QueryParam("page")
	ipp := c.QueryParam("quantity")

	page, _ = strconv.ParseInt(pg, 10, 64)
	quantity, _ = strconv.ParseInt(ipp, 10, 64)

	if page < 1 {
		page = 1
	}

	if quantity < 1 || quantity > 1000 {
		quantity = 10
	}

	return
}

// GetMultipleQueryParam returns a list of values for multiple query params
func GetMultipleQueryParam(c echo.Context, paramName string) (retVal []string) {
	retVal = make([]string, 0)

	for k, param := range map[string][]string(c.QueryParams()) {
		if k == paramName {
			for _, value := range param {
				retVal = append(retVal, value)
			}
			break
		}
	}

	return retVal
}

// GetMultipleIntQueryParam returns a list of integer values from multiple query params
func GetMultipleIntQueryParam(c echo.Context, paramName string) (retVal []int64, err error) {
	retVal = make([]int64, 0)

	for _, value := range GetMultipleQueryParam(c, paramName) {
		intValue, err := strconv.ParseInt(value, 10, 64)
		if err != nil {
			return retVal, errors.Wrap(err)
		}
		retVal = append(retVal, intValue)
	}

	return retVal, nil
}
