package responses

import (
	"errors"
	"fmt"
	"github.com/json-iterator/go"
	"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
	"io/ioutil"
	"net/http"
	"strings"
)

type AcsResponse interface {
	IsSuccess() bool
	GetHttpStatus() int
	GetHttpHeaders() map[string][]string
	GetHttpContentString() string
	GetHttpContentBytes() []byte
	GetOriginHttpResponse() *http.Response
	parseFromHttpResponse(httpResponse *http.Response) error
}

type BaseResponse struct {
	httpStatus         int
	httpHeaders        map[string][]string
	httpContentString  string
	httpContentBytes   []byte
	originHttpResponse *http.Response

	Code   int    `json:"code"`
	Status bool   `json:"status"`
	Msg    string `json:"msg"`
}

func (baseResponse *BaseResponse) GetHttpStatus() int {
	return baseResponse.httpStatus
}

func (baseResponse *BaseResponse) GetHttpHeaders() map[string][]string {
	return baseResponse.httpHeaders
}

func (baseResponse *BaseResponse) GetHttpContentString() string {
	return baseResponse.httpContentString
}

func (baseResponse *BaseResponse) GetHttpContentBytes() []byte {
	return baseResponse.httpContentBytes
}

func (baseResponse *BaseResponse) GetOriginHttpResponse() *http.Response {
	return baseResponse.originHttpResponse
}

func (baseResponse *BaseResponse) IsSuccess() bool {
	if baseResponse.GetHttpStatus() >= 200 && baseResponse.GetHttpStatus() < 300 {
		return true
	}
	return false
}

func (baseResponse *BaseResponse) parseFromHttpResponse(httpResponse *http.Response) (err error) {
	defer httpResponse.Body.Close()
	body, err := ioutil.ReadAll(httpResponse.Body)
	if err != nil {
		return
	}
	baseResponse.httpStatus = httpResponse.StatusCode
	baseResponse.httpHeaders = httpResponse.Header
	baseResponse.httpContentBytes = body
	baseResponse.httpContentString = string(body)
	baseResponse.originHttpResponse = httpResponse
	return
}

type CommonResponse struct {
	*BaseResponse
}

func NewCommonResponse() (response *CommonResponse) {
	return &CommonResponse{
		BaseResponse: &BaseResponse{},
	}
}

func Unmarshal(response AcsResponse, httpResponse *http.Response, format string) (err error) {
	err = response.parseFromHttpResponse(httpResponse)
	if err != nil {
		return
	}

	if _, isCommonResponse := response.(CommonResponse); isCommonResponse {
		return
	}

	if !response.IsSuccess() {
		if contentType, ok := response.GetHttpHeaders()["Content-Type"]; ok {
			for _, v := range contentType {
				if strings.Contains(v, requests.Json) {
					err = jsoniter.Unmarshal(response.GetHttpContentBytes(), response)
					if err != nil {
						return errors.New("json Unmarshal:" + err.Error())
					}
					break
				}
			}
		}

		err = errors.New(fmt.Sprintf("%d %s", response.GetHttpStatus(), response.GetHttpContentString()))
		return
	}

	if format != "xml" {
		err = jsoniter.Unmarshal(response.GetHttpContentBytes(), response)
		if err != nil {
			return errors.New("json Unmarshal:" + err.Error())
		}
	}
	return
}