package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

const template = `// This file was generated by _tools/gen-deifinition.go. DO NOT EDIT.

package definition
import "sync"

var %[1]s Emojis
var %[1]sOnce sync.Once

func %[2]s(opts ...EmojisOption) Emojis {
	%[1]sOnce.Do(func() {
		%[1]s = NewEmojis(
			 %[3]s,
        )
	})
	m := %[1]s.Clone()
	for _, opt := range opts {
		opt(m)
	}
	return m
}
`

const outBaseDir = "../definition/"

func main() {
	fmt.Println("generate github")
	genGithub()
}

func abortIfError(err error) {
	if err != nil {
		fmt.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}

func getURL(url string) []byte {
	resp, err := http.Get(url)
	if err != nil {
		fmt.Fprint(os.Stderr, err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	bs, err := ioutil.ReadAll(resp.Body)
	abortIfError(err)
	return bs
}

func genGithub() {
	name := "github"
	nameCap := "Github"
	outPath := outBaseDir + "github.go"

	bs := getURL("https://api.github.com/emojis")
	var ghnames map[string]string
	abortIfError(json.Unmarshal(bs, &ghnames))

	bs = getURL("https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json")
	var list []map[string]interface{}
	abortIfError(json.Unmarshal(bs, &list))

	getShortNames := func(emoji map[string]interface{}) []string {
		ns := []string{}
		for _, name := range emoji["aliases"].([]interface{}) {
			ns = append(ns, name.(string))
		}
		return ns
	}
	getUnicode := func(emoji map[string]interface{}) string {
		return emoji["emoji"].(string)
	}
	getDescription := func(emoji map[string]interface{}) string {
		return emoji["description"].(string)
	}

	buf := []string{}
	for _, emoji := range list {
		names := getShortNames(emoji)
		name := ""
		for _, n := range names {
			if _, ok := ghnames[n]; ok {
				name = n
				break
			}
		}
		if len(name) == 0 {
			continue
		}
		desc := getDescription(emoji)

		buf = append(buf, fmt.Sprintf(`NewEmoji("%s", %#v, "%s")`, desc, []rune(getUnicode(emoji)), name))
	}

	f, err := os.Create(outPath)
	abortIfError(err)
	defer f.Close()
	_, err = f.WriteString(fmt.Sprintf(template, name, nameCap, strings.Join(buf, ",\n\t\t\t")))
	abortIfError(err)
}
