package ws

import (
	"encoding/json"
	"reflect"
)

type envelope struct {
	MessageType string          `json:"type"`
	Message     json.RawMessage `json:"data"`
}

type JSONMessageCodec struct{}

func NewJSONMessageCodec() *JSONMessageCodec {
	s := new(JSONMessageCodec)
	return s
}

func (s *JSONMessageCodec) EncodeMessage(messageType string, message interface{}) (data []byte, err error) {
	paramData, err := json.Marshal(message)
	if err != nil {
		return
	}
	data, err = json.Marshal(envelope{
		MessageType: messageType,
		Message:     paramData,
	})
	return
}

func (s *JSONMessageCodec) DecodeMessageHeader(encoded []byte) (procName string, messageBody []byte, err error) {
	var env envelope
	err = json.Unmarshal(encoded, &env)
	if err != nil {
		return
	}
	return env.MessageType, env.Message, nil
}

func (s *JSONMessageCodec) DecodeMessageBody(messageBody []byte, argType reflect.Type) (instance reflect.Value, err error) {
	instance = reflect.New(argType)
	err = json.Unmarshal(messageBody, instance.Interface())
	if err != nil {
		return
	}
	return
}
