package msgpack

import (
	"bytes"
	"math/big"
	"sort"

	"github.com/vmihailenco/msgpack"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/convert"
)

// Marshal produces a msgpack serialization of the given value that
// can be decoded into the given type later using Unmarshal.
//
// The given value must conform to the given type, or an error will
// be returned.
func Marshal(val cty.Value, ty cty.Type) ([]byte, error) {
	errs := val.Type().TestConformance(ty)
	if errs != nil {
		// Attempt a conversion
		var err error
		val, err = convert.Convert(val, ty)
		if err != nil {
			return nil, err
		}
	}

	// From this point onward, val can be assumed to be conforming to t.

	var path cty.Path
	var buf bytes.Buffer
	enc := msgpack.NewEncoder(&buf)

	err := marshal(val, ty, path, enc)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func marshal(val cty.Value, ty cty.Type, path cty.Path, enc *msgpack.Encoder) error {
	// If we're going to decode as DynamicPseudoType then we need to save
	// dynamic type information to recover the real type.
	if ty == cty.DynamicPseudoType && val.Type() != cty.DynamicPseudoType {
		return marshalDynamic(val, path, enc)
	}

	if !val.IsKnown() {
		err := enc.Encode(unknownVal)
		if err != nil {
			return path.NewError(err)
		}
		return nil
	}
	if val.IsNull() {
		err := enc.EncodeNil()
		if err != nil {
			return path.NewError(err)
		}
		return nil
	}

	// The caller should've guaranteed that the given val is conformant with
	// the given type ty, so we'll proceed under that assumption here.
	switch {
	case ty.IsPrimitiveType():
		switch ty {
		case cty.String:
			err := enc.EncodeString(val.AsString())
			if err != nil {
				return path.NewError(err)
			}
			return nil
		case cty.Number:
			var err error
			switch {
			case val.RawEquals(cty.PositiveInfinity):
				err = enc.EncodeFloat64(positiveInfinity)
			case val.RawEquals(cty.NegativeInfinity):
				err = enc.EncodeFloat64(negativeInfinity)
			default:
				bf := val.AsBigFloat()
				if iv, acc := bf.Int64(); acc == big.Exact {
					err = enc.EncodeInt(iv)
				} else if fv, acc := bf.Float64(); acc == big.Exact {
					err = enc.EncodeFloat64(fv)
				} else {
					err = enc.EncodeString(bf.Text('f', -1))
				}
			}
			if err != nil {
				return path.NewError(err)
			}
			return nil
		case cty.Bool:
			err := enc.EncodeBool(val.True())
			if err != nil {
				return path.NewError(err)
			}
			return nil
		default:
			panic("unsupported primitive type")
		}
	case ty.IsListType(), ty.IsSetType():
		enc.EncodeArrayLen(val.LengthInt())
		ety := ty.ElementType()
		it := val.ElementIterator()
		path := append(path, nil) // local override of 'path' with extra element
		for it.Next() {
			ek, ev := it.Element()
			path[len(path)-1] = cty.IndexStep{
				Key: ek,
			}
			err := marshal(ev, ety, path, enc)
			if err != nil {
				return err
			}
		}
		return nil
	case ty.IsMapType():
		enc.EncodeMapLen(val.LengthInt())
		ety := ty.ElementType()
		it := val.ElementIterator()
		path := append(path, nil) // local override of 'path' with extra element
		for it.Next() {
			ek, ev := it.Element()
			path[len(path)-1] = cty.IndexStep{
				Key: ek,
			}
			var err error
			err = marshal(ek, ek.Type(), path, enc)
			if err != nil {
				return err
			}
			err = marshal(ev, ety, path, enc)
			if err != nil {
				return err
			}
		}
		return nil
	case ty.IsTupleType():
		etys := ty.TupleElementTypes()
		it := val.ElementIterator()
		path := append(path, nil) // local override of 'path' with extra element
		i := 0
		enc.EncodeArrayLen(len(etys))
		for it.Next() {
			ety := etys[i]
			ek, ev := it.Element()
			path[len(path)-1] = cty.IndexStep{
				Key: ek,
			}
			err := marshal(ev, ety, path, enc)
			if err != nil {
				return err
			}
			i++
		}
		return nil
	case ty.IsObjectType():
		atys := ty.AttributeTypes()
		path := append(path, nil) // local override of 'path' with extra element

		names := make([]string, 0, len(atys))
		for k := range atys {
			names = append(names, k)
		}
		sort.Strings(names)

		enc.EncodeMapLen(len(names))

		for _, k := range names {
			aty := atys[k]
			av := val.GetAttr(k)
			path[len(path)-1] = cty.GetAttrStep{
				Name: k,
			}
			var err error
			err = marshal(cty.StringVal(k), cty.String, path, enc)
			if err != nil {
				return err
			}
			err = marshal(av, aty, path, enc)
			if err != nil {
				return err
			}
		}
		return nil
	case ty.IsCapsuleType():
		return path.NewErrorf("capsule types not supported for msgpack encoding")
	default:
		// should never happen
		return path.NewErrorf("cannot msgpack-serialize %s", ty.FriendlyName())
	}
}

// marshalDynamic adds an extra wrapping object containing dynamic type
// information for the given value.
func marshalDynamic(val cty.Value, path cty.Path, enc *msgpack.Encoder) error {
	dv := dynamicVal{
		Value: val,
		Path:  path,
	}
	return enc.Encode(&dv)
}
