// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore

package main

import (
	"bytes"
	"log"
	"sort"
	"strings"

	"golang.org/x/text/internal/gen"
	"golang.org/x/text/internal/gen/bitfield"
	"golang.org/x/text/internal/ucd"
)

var (
	// computed by computeDirectOffsets
	directOffsets = map[string]int{}
	directData    bytes.Buffer

	// computed by computeEntries
	entries    []entry
	singleData bytes.Buffer
	index      []uint16
)

type entry struct {
	start    rune `bitfield:"21,startRune"`
	numRunes int  `bitfield:"16"`
	end      rune
	index    int  `bitfield:"16"`
	base     int  `bitfield:"6"`
	direct   bool `bitfield:""`
	name     string
}

func main() {
	gen.Init()

	w := gen.NewCodeWriter()
	defer w.WriteVersionedGoFile("tables.go", "runenames")

	gen.WriteUnicodeVersion(w)

	computeDirectOffsets()
	computeEntries()

	if err := bitfield.Gen(w, entry{}, nil); err != nil {
		log.Fatal(err)
	}

	type entry uint64 // trick the generation code to use the entry type
	packed := []entry{}
	for _, e := range entries {
		e.numRunes = int(e.end - e.start + 1)
		v, err := bitfield.Pack(e, nil)
		if err != nil {
			log.Fatal(err)
		}
		packed = append(packed, entry(v))
	}

	index = append(index, uint16(singleData.Len()))

	w.WriteVar("entries", packed)
	w.WriteVar("index", index)
	w.WriteConst("directData", directData.String())
	w.WriteConst("singleData", singleData.String())
}

func computeDirectOffsets() {
	counts := map[string]int{}

	p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
	for p.Next() {
		start, end := p.Range(0)
		counts[getName(p)] += int(end-start) + 1
	}

	direct := []string{}
	for k, v := range counts {
		if v > 1 {
			direct = append(direct, k)
		}
	}
	sort.Strings(direct)

	for _, s := range direct {
		directOffsets[s] = directData.Len()
		directData.WriteString(s)
	}
}

func computeEntries() {
	p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
	for p.Next() {
		start, end := p.Range(0)

		last := entry{}
		if len(entries) > 0 {
			last = entries[len(entries)-1]
		}

		name := getName(p)
		if index, ok := directOffsets[name]; ok {
			if last.name == name && last.end+1 == start {
				entries[len(entries)-1].end = end
				continue
			}
			entries = append(entries, entry{
				start:  start,
				end:    end,
				index:  index,
				base:   len(name),
				direct: true,
				name:   name,
			})
			continue
		}

		if start != end {
			log.Fatalf("Expected start == end, found %x != %x", start, end)
		}

		offset := singleData.Len()
		base := offset >> 16
		index = append(index, uint16(offset))
		singleData.WriteString(name)

		if last.base == base && last.end+1 == start {
			entries[len(entries)-1].end = start
			continue
		}

		entries = append(entries, entry{
			start: start,
			end:   end,
			index: len(index) - 1,
			base:  base,
			name:  name,
		})
	}
}

func getName(p *ucd.Parser) string {
	s := p.String(ucd.Name)
	if s == "" {
		return ""
	}
	if s[0] == '<' {
		const first = ", First>"
		if i := strings.Index(s, first); i >= 0 {
			s = s[:i] + ">"
		}

	}
	return s
}
