package pe

import "git.urbach.dev/cli/q/src/dll"

// importLibraries generates the import address table which contains the addresses of functions imported from DLLs.
func importLibraries(dlls dll.List, importsStart int) ([]uint64, []byte, []DLLImport, int) {
	imports := make([]uint64, 0)
	dllData := make([]byte, 0)
	dllImports := []DLLImport{}

	for library := range dlls.All() {
		functionsStart := len(imports) * 8
		dllNamePos := len(dllData)
		dllData = append(dllData, library.Name...)
		dllData = append(dllData, ".dll"...)
		dllData = append(dllData, 0x00)

		dllImports = append(dllImports, DLLImport{
			RvaFunctionNameList:    uint32(importsStart + functionsStart),
			TimeDateStamp:          0,
			ForwarderChain:         0,
			RvaModuleName:          uint32(dllNamePos),
			RvaFunctionAddressList: uint32(importsStart + functionsStart),
		})

		for _, fn := range library.Functions {
			if len(dllData)&1 != 0 {
				dllData = append(dllData, 0x00) // align the next entry on an even boundary
			}

			offset := len(dllData)
			dllData = append(dllData, 0x00, 0x00)
			dllData = append(dllData, fn...)
			dllData = append(dllData, 0x00)

			imports = append(imports, uint64(offset))
		}

		imports = append(imports, 0)
	}

	dllDataStart := importsStart + len(imports)*8

	for i := range imports {
		if imports[i] == 0 {
			continue
		}

		imports[i] += uint64(dllDataStart)
	}

	for i := range dllImports {
		dllImports[i].RvaModuleName += uint32(dllDataStart)
	}

	// a zeroed structure marks the end of the list
	dllImports = append(dllImports, DLLImport{})

	return imports, dllData, dllImports, dllDataStart
}