package main

import (
	"encoding/hex"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
)

const (
	SizeOfOneRow = 20

	NameOfOutputFile = "bin.c"
	TypeOfArray      = "static const unsigned char "
	PrefixOfArray    = "_ac"
)

type FileInfo struct {
	path string
	name string
}

// list all files in folders and subFolder, return bin FineInfo
func gatherFiles(path string) []FileInfo {
	var files []FileInfo
	var oneFile FileInfo

	listFile, _ := ioutil.ReadDir(path)
	oneFile.path = path + "\\"

	for _, f := range listFile {
		if f.IsDir() {
			listSubFile, _ := ioutil.ReadDir(path)
			oneFile.path = path + "\\"

			for _, subF := range listSubFile {
				if subF.Name()[strings.LastIndex(subF.Name(), ".")+1:] == "bin" {
					oneFile.name = subF.Name()
					files = append(files, oneFile)
				}
			}
		} else if f.Name()[strings.LastIndex(f.Name(), ".")+1:] == "bin" {
			oneFile.name = f.Name()
			files = append(files, oneFile)
		}
	}

	return files
}

// create c file and write all bin data
func bin2C(fileInfo []FileInfo, outputPath string) {
	outputFile, _ := os.Create(outputPath + "\\" + NameOfOutputFile)
	defer outputFile.Close()

	for _, v := range fileInfo {
		outputFile.WriteString(convertOne(v))
		outputFile.WriteString("\n\n/*****************************************************")
		outputFile.WriteString(" end of file ")
		outputFile.WriteString("*****************************************************/\n\n")
	}
}

// convert one bin file, return all data in string type
func convertOne(fileInfo FileInfo) string {
	var retStr string
	binData, _ := ioutil.ReadFile(fileInfo.path + fileInfo.name)

	// remove file type and spaces
	fileName := fileInfo.name[:strings.Index(fileInfo.name, ".")]
	fileName = strings.ReplaceAll(fileName, " ", "")

	// write file header
	retStr = TypeOfArray + PrefixOfArray + fileName + "[" + strconv.Itoa(len(binData)) + "UL] = {\n  "

	// write all data, add \n in suitable place
	for k, v := range binData {
		retStr += "0x" + strings.ToUpper(hex.EncodeToString([]byte{v}))
		if (k + 1) != len(binData) {
			retStr += ", "
		}
		if k != 0 && ((k+1)%SizeOfOneRow) == 0 && (k+1) != len(binData) {
			retStr += "\n  "
		}
	}

	return retStr + "\n};"
}

func main() {
	bin2C(gatherFiles("."), ".")
}
