package main

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

const template = `// This file was generated by _tools/gen-definitions.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 {
		var names []string
		for _, n := range getShortNames(emoji) {
			if _, ok := ghNames[n]; len(n) > 0 && ok {
				names = append(names, fmt.Sprintf(`"%s"`, n))
			}
		}
		if len(names) == 0 {
			continue
		}

		desc := getDescription(emoji)
		uc := []rune(getUnicode(emoji))
		buf = append(buf, fmt.Sprintf(`Emoji{Name: "%s", Unicode: %#v, ShortNames: []string{%s}}`, desc, uc, strings.Join(names, ", ")))
	}

	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)
}
