package main

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

func main() {
	var result []byte
	result = encodeString("hello")
	fmt.Println(string(result))

	result = encodeInt(25)
	fmt.Println(string(result))

	result = encodeMap(map[string]string{"color": "green", "temperature": "95", "speed": "100"})
	fmt.Println(string(result))

	result = encodeMarshaler(Email{name: "gopher", domain: "golang.org"})
	fmt.Println(string(result))
}

// #TODO: Create a general function called `encode` that can take any type and call the corresponding
// encoder based on the corresponding type or interface
func encode(v interface{}) {
	var result []byte

	// Hint: a switch statement on type is very useful here...

	// Check for a string
	// Check for an int
	// Check for a map[string]string
	// Check to see if it already supports marshaling (it defines the json.Marshaler interface)

	fmt.Println(string(result))
}

// Nothing to do beyond this point.

func encodeMarshaler(m json.Marshaler) []byte {
	b, err := m.MarshalJSON()
	if err != nil {
		panic(fmt.Sprintf("error encoding %T: %s\n", m, err))
	}
	return b
}

func encodeMap(m map[string]string) []byte {
	js := "{"
	for k, v := range m {
		js = js + `"` + k + `":"` + v + `" `
	}
	js = js + "}"
	return []byte(js)
}

func encodeString(s string) []byte {
	fmt := `{"value":"` + s + `"}"`
	return []byte(fmt)
}

func encodeInt(i int) []byte {
	fmt := `{"value":"` + strconv.Itoa(i) + `"}"`
	return []byte(fmt)
}

type Email struct {
	name   string
	domain string
}

func (e Email) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf("{\"email\":\"%s@%s\"}", e.name, e.domain)), nil
}
