package main

import (
	"encoding/binary"
	"fmt"
	"os"
	"red-green/door"
	"strings"
)

func ListFonts(filename string) {

	f, err := os.Open(filename)
	if err != nil {
		fmt.Printf("Open(%s): %s\n", filename, err)
		panic(err)
	}
	defer f.Close()
	fmt.Println(filename, ":")

	tdfonts := make([]byte, 20)
	f.Read(tdfonts)
	for {
		fontdef := make([]byte, 4)
		read, _ := f.Read(fontdef)
		if read != 4 {
			break
		}
		fontname := make([]byte, 13)
		f.Read(fontname)
		Name := strings.Trim(string(fontname[1:]), "\x00")
		// fmt.Printf("Font: %s\n", Name)
		f.Read(fontdef)
		single := make([]byte, 1)

		var FontType int8
		binary.Read(f, binary.LittleEndian, &FontType)

		// f.Read(single) // FontType
		// FontType := int(single[0])
		fmt.Printf("Font: %s (type %d)\n", Name, FontType)
		f.Read(single) // Spacing

		// blocksize := make([]byte, 2)
		// f.Read(blocksize)

		var BlockSize int16
		binary.Read(f, binary.LittleEndian, &BlockSize)
		// fmt.Printf("Size: %d / %x\n", BlockSize, BlockSize)

		letterOffsets := make([]int16, 94)
		binary.Read(f, binary.LittleEndian, &letterOffsets)

		if false {
			for idx, i := range letterOffsets {
				fmt.Printf(" %04X", i)
				if (idx+1)%10 == 0 {
					fmt.Println("")
				}
			}
			fmt.Println("")
		}

		data := make([]byte, BlockSize)
		binary.Read(f, binary.LittleEndian, &data)
	}
}

func byte_to_text(line []byte) string {
	var output string

	for _, ch := range line {
		output += fmt.Sprintf("0x%02x, ", ch)
	}
	if len(output) > 0 {
		output = output[:len(output)-2]
	}
	return output
}

/*
func text_to_hextext(line string) string {
	var output string
	// output = "\""
	for _, ch := range []byte(line) {
		// output += fmt.Sprintf("\\x%02x", ch)
		output += fmt.Sprintf("0x%02x,", ch)
	}
	if len(output) > 1 {
		output = output[:len(output)-1]
	}
	// output += "\""
	return output
}
*/

func ExtractColor(name string, offsets []uint16, data []byte) (Font door.ColorFont) {

	defer func() {
		if r := recover(); r != nil {
			// Ok, this failed
			Font = door.ColorFont{}
		}
	}()

	var indexes []int
	var blocks [][][]byte
	var current [][]byte
	var line []byte

	pos := 0
	for pos < len(data) {
		indexes = append(indexes, pos)
		current = make([][]byte, 0)
		line = make([]byte, 0)

		// We don't use these.
		// w = data[pos]
		// h = data[pos+1]

		pos += 2

		// process this character
		for pos < len(data) {
			ch := data[pos]
			pos++
			if ch == 0x00 {
				// end of character
				current = append(current, line)
				blocks = append(blocks, current)
				// current = make([][]byte, 0)
				// line = make([]byte, 0)
				break
			}
			if ch == 0x0d {
				// end of this character line
				current = append(current, line)
				line = make([]byte, 0)
				continue
			}
			if ch == 0x26 {
				// & descender mark
				continue
			}
			line = append(line, ch)
			color := data[pos]
			pos++
			line = append(line, color)
		}

	}

	// offset optimization:
	var single []int
	for _, o := range offsets {
		if o == 65535 {
			single = append(single, -1)
			continue
		}
		found := false
		for idx, i := range indexes {
			if o == uint16(i) {
				single = append(single, idx)
				found = true
				break
			}
		}
		if !found {
			panic(fmt.Sprintf("Unable to locate index %d / %x (font appears corrupted)", o, o))
		}
	}

	return door.ColorFont{Characters: single, Data: blocks}
}

func ExtractBlock(name string, offsets []uint16, data []byte) (Font door.BlockFont) {

	defer func() {
		if r := recover(); r != nil {
			// Ok, this failed
			Font = door.BlockFont{}
		}
	}()

	// fmt.Printf("Extract Block Font: %s\n", name)
	var indexes []int
	var blocks [][][]byte
	var current [][]byte
	var line []byte

	pos := 0
	for pos < len(data) {
		indexes = append(indexes, pos)
		current = make([][]byte, 0)
		line = make([]byte, 0)

		// We don't use these
		// w = data[pos]
		// h = data[pos+1]
		pos += 2

		// process this character
		for pos < len(data) {
			ch := data[pos]
			pos++

			if ch == 0x00 {
				// end of character
				current = append(current, line)
				blocks = append(blocks, current)
				// current = make([][]byte, 0)
				// line = make([]byte, 0)
				break
			}
			if ch == 0x0d {
				// end of this character line
				current = append(current, line)
				line = make([]byte, 0)
				continue
			}
			if ch == 0x26 {
				// & descender mark
				continue
			}
			line = append(line, ch)
		}
	}

	// offset optimization:
	var single []int
	for _, o := range offsets {
		if o == 65535 {
			single = append(single, -1)
			continue
		}
		found := false
		for idx, i := range indexes {
			if o == uint16(i) {
				single = append(single, idx)
				found = true
				break
			}
		}
		if !found {
			panic(fmt.Sprintf("Unable to locate index %d / %x (font appears corrupted)", o, o))
		}
	}

	return door.BlockFont{Characters: single, Data: blocks}
}