package reflective

import (
	"bytes"
	"fmt"
	"reflect"
)

// An InvalidUnmarshalError describes an invalid argument passed to New.
// (It must be a non-nil pointer.)
type InvalidUnmarshalError struct {
	Method string
	Prefix string

	reflect.Type
}

func (e *InvalidUnmarshalError) Error() string {
	var buf bytes.Buffer

	if e.Prefix != "" {
		_, _ = fmt.Fprintf(&buf, "%s: ", e.Prefix)
	}

	method := e.Method
	if method == "" {
		method = "New"
	}

	_, _ = fmt.Fprintf(&buf, "%s(", method)

	switch {
	case e.Type == nil:
		_, _ = buf.WriteString("nil")
	case e.Type.Kind() != reflect.Pointer:
		_, _ = fmt.Fprintf(&buf, "%s %s", "non-pointer", e.Type.String())
	default:
		_, _ = fmt.Fprintf(&buf, "%s %s", "nil", e.Type.String())
	}

	_, _ = buf.WriteString(")")

	return buf.String()
}

// An UnmarshalTypeError tells something went wrong while processing
// a type.
type UnmarshalTypeError struct {
	Prefix string
	Err    error

	reflect.Type
}

func (e UnmarshalTypeError) Unwrap() error {
	return e.Err
}

func (e UnmarshalTypeError) Error() string {
	var buf bytes.Buffer

	if e.Prefix != "" {
		_, _ = fmt.Fprintf(&buf, "%s: ", e.Prefix)
	}

	_, _ = fmt.Fprintf(&buf, "%s: %s", e.Type.String(), e.Err)

	return buf.String()
}