package dtl

import (
	"bytes"
	"encoding/json"
	"fmt"
)

type azureErrorDetails struct {
	Code    string              `json:"code"`
	Message string              `json:"message"`
	Details []azureErrorDetails `json:"details"`
}

type azureErrorResponse struct {
	ErrorDetails azureErrorDetails `json:"error"`
}

func newAzureErrorResponse(s string) *azureErrorResponse {
	var errorResponse azureErrorResponse
	err := json.Unmarshal([]byte(s), &errorResponse)
	if err == nil {
		return &errorResponse
	}

	return nil
}

func (e *azureErrorDetails) isEmpty() bool {
	return e.Code == ""
}

func (e *azureErrorResponse) Error() string {
	var buf bytes.Buffer
	//buf.WriteString("-=-=- ERROR -=-=-")
	formatAzureErrorResponse(e.ErrorDetails, &buf, "")
	//buf.WriteString("-=-=- ERROR -=-=-")
	return buf.String()
}

// format a Azure Error Response by recursing through the JSON structure.
//
// Errors may contain nested errors, which are JSON documents that have been
// serialized and escaped.  Keep following this nesting all the way down...
func formatAzureErrorResponse(error azureErrorDetails, buf *bytes.Buffer, indent string) {
	if error.isEmpty() {
		return
	}

	buf.WriteString(fmt.Sprintf("ERROR: %s-> %s : %s\n", indent, error.Code, error.Message))
	for _, x := range error.Details {
		newIndent := fmt.Sprintf("%s  ", indent)

		var aer azureErrorResponse
		err := json.Unmarshal([]byte(x.Message), &aer)
		if err == nil {
			buf.WriteString(fmt.Sprintf("ERROR: %s-> %s\n", newIndent, x.Code))
			formatAzureErrorResponse(aer.ErrorDetails, buf, newIndent)
		} else {
			buf.WriteString(fmt.Sprintf("ERROR: %s-> %s : %s\n", newIndent, x.Code, x.Message))
		}
	}
}
