// Package request...
//
// Description : 解析请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-07-24 8:53 下午
package request

import (
	"encoding/json"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"

	"git.zhangdeman.cn/zhangdeman/gopkg/easymap"
	"github.com/pkg/errors"

	"github.com/gin-gonic/gin"
)

// ParseRequestParam 解析请求数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:52 下午 2021/9/14
func ParseRequestParam(ctx *gin.Context) (easymap.EasyMap, error) {
	switch ctx.Request.Method {
	case http.MethodPost:
		return ParsePostRequestBody(ctx)
	default:
		return ParseGetRequestBody(ctx)
	}
}

// ParseGetRequestURI 解析URL请求参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:03 下午 2021/7/24
func ParseGetRequestURI(url *url.URL) map[string][]string {
	url.RawQuery = strings.TrimSpace(url.RawQuery)
	parseResult := make(map[string][]string)
	if len(url.RawQuery) == 0 {
		return parseResult
	}
	requestURIArr := strings.Split(url.RawQuery, "&")
	for _, kvPair := range requestURIArr {
		kvPair = strings.TrimSpace(kvPair)
		if len(kvPair) == 0 {
			continue
		}
		kvArr := strings.Split(kvPair, "=")
		_, keyExist := parseResult[kvArr[0]]
		if len(kvArr) == 1 {
			// 识别到 ?a=1&b=2&c 这种格式,默认补齐成 ?a=1&b=2&c=
			if keyExist {
				parseResult[kvPair] = append(parseResult[kvPair], "")
			} else {
				parseResult[kvPair] = []string{""}
			}
			continue
		}
		// 兼容参数值中包含=的情况
		if keyExist {
			parseResult[kvArr[0]] = append(parseResult[kvArr[0]], strings.Join(kvArr[1:], "="))
		} else {
			parseResult[kvArr[0]] = []string{strings.Join(kvArr[1:], "=")}
		}
	}
	return parseResult
}

// ParseGetRequestBody 解析get请求的body
//
// Author : zhangdeman001@ke.com<白茶清欢>
//
// Date : 9:07 下午 2021/7/24
func ParseGetRequestBody(ctx *gin.Context) (easymap.EasyMap, error) {
	result := easymap.NewNormal(true)
	urlRaw := strings.TrimLeft(ctx.Request.URL.RawQuery, "/")
	queryArr := strings.Split(urlRaw, "&")
	for _, itemPair := range queryArr {
		itemPairArr := strings.Split(itemPair, "=")
		if len(itemPairArr) == 0 {
			continue
		}
		if len(itemPairArr) == 1 {
			result.Set(itemPairArr[0], "")
		} else {
			result.Set(itemPairArr[0], strings.Join(itemPairArr[1:], "="))
		}
	}
	return result, nil
}

// ParsePostRequestBody 解析post请求参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 7:38 下午 2021/9/14
func ParsePostRequestBody(ctx *gin.Context) (easymap.EasyMap, error) {
	contentType := strings.ToLower(ctx.ContentType())
	if strings.Contains(contentType, "application/json") {
		// application/json 请求参数
		return ParsePostRequestForApplicationJSON(ctx)
	}

	if strings.Contains(contentType, "x-www-form-urlencoded") {
		// Content-Type: application/x-www-form-urlencoded 请求方法
		return ParsePostRequestForApplicationFormURLEncoded(ctx)
	}

	if strings.Contains(contentType, "form-data") {
		// multipart/form-data 请求方法
		return ParsePostRequestForFormData(ctx)
	}
	return easymap.NewNormal(true), errors.New("content-type : " + contentType + " is not support")
}

// ParsePostRequestForApplicationJSON 解析application/json请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:00 下午 2021/9/14
func ParsePostRequestForApplicationJSON(ctx *gin.Context) (easymap.EasyMap, error) {
	var (
		err    error
		result map[string]interface{}
	)
	finalResult := easymap.NewNormal(true)
	decoder := json.NewDecoder(ctx.Request.Body)
	decoder.UseNumber()
	if err = decoder.Decode(&result); nil != err {
		return finalResult, err
	}
	for k, v := range result {
		finalResult.Set(k, v)
	}
	return finalResult, nil
}

// ParsePostRequestForApplicationFormURLEncoded 解析 application/x-www-form-urlencoded 表单
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:11 下午 2021/9/14
func ParsePostRequestForApplicationFormURLEncoded(ctx *gin.Context) (easymap.EasyMap, error) {
	var (
		err      error
		result   easymap.EasyMap
		byteData []byte
	)

	result = easymap.NewNormal(true)
	if byteData, err = io.ReadAll(ctx.Request.Body); nil != err {
		return result, err
	}

	tmpResult := make(map[string][]string)
	orgArr := strings.Split(string(byteData), "&")
	for _, kvPair := range orgArr {
		kv := strings.Split(kvPair, "=")
		if len(kv) == 0 {
			continue
		}

		if _, exist := tmpResult[kv[0]]; !exist {
			tmpResult[kv[0]] = make([]string, 0)
		}
		if len(kv) == 1 {
			tmpResult[kv[0]] = append(tmpResult[kv[0]], "")
		} else {
			tmpResult[kv[0]] = append(tmpResult[kv[0]], strings.Join(kv[1:], "="))
		}
	}

	for k, v := range tmpResult {
		result.Set(k, v)
	}

	return result, err
}

// ParsePostRequestForFormData 解析 multipart/form-data 表单数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:17 下午 2021/9/14
func ParsePostRequestForFormData(ctx *gin.Context) (easymap.EasyMap, error) {
	var (
		err    error
		result easymap.EasyMap
		tmp    *multipart.Form
	)

	result = easymap.NewNormal(true)
	if tmp, err = ctx.MultipartForm(); nil != err {
		return result, err
	}

	for k, v := range tmp.Value {
		result.Set(k, v)
	}

	return result, nil
}