// Package smbios implements parsing of SMBIOS data structures.
// SMBIOS data is commonly populated by platform firmware to convey various
// metadata (including name, vendor, slots and serial numbers) about the
// platform to the operating system.
// The SMBIOS standard is maintained by DMTF and available at
// https://www.dmtf.org/sites/default/files/standards/documents/
// DSP0134_3.6.0.pdf. The rest of this package just refers to it as "the
// standard".
package smbios

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"reflect"
	"strings"
)

// See spec section 6.1.2
type structureHeader struct {
	// Types 128 through 256 are reserved for OEM and system-specific use.
	Type uint8
	// Length of the structure including this header, excluding the string
	// set.
	Length uint8
	// Unique handle for this structure.
	Handle uint16
}

type Structure struct {
	Type             uint8
	Handle           uint16
	FormattedSection []byte
	Strings          []string
}

// Table represents a decoded SMBIOS table consisting of its structures.
// A few known structures are parsed if present, the rest is put into
// Structures unparsed.
type Table struct {
	BIOSInformationRaw       *BIOSInformationRaw
	SystemInformationRaw     *SystemInformationRaw
	BaseboardsInformationRaw []*BaseboardInformationRaw
	SystemSlotsRaw           []*SystemSlotRaw
	MemoryDevicesRaw         []*MemoryDeviceRaw

	Structures []Structure
}

const (
	structTypeInactive   = 126
	structTypeEndOfTable = 127
)

func Unmarshal(table *bufio.Reader) (*Table, error) {
	var tbl Table
	for {
		var structHdr structureHeader
		if err := binary.Read(table, binary.LittleEndian, &structHdr); err != nil {
			if err == io.EOF {
				// Be tolerant of EOFs on structure boundaries even though
				// the EOT marker is specified as a type 127 structure.
				break
			}
			return nil, fmt.Errorf("unable to read structure header: %w", err)
		}
		if int(structHdr.Length) < binary.Size(structHdr) {
			return nil, fmt.Errorf("invalid structure: header length (%d) smaller than header", structHdr.Length)
		}
		if structHdr.Type == structTypeEndOfTable {
			break
		}
		var s Structure
		s.Type = structHdr.Type
		s.Handle = structHdr.Handle
		s.FormattedSection = make([]byte, structHdr.Length-uint8(binary.Size(structHdr)))
		if _, err := io.ReadFull(table, s.FormattedSection); err != nil {
			return nil, fmt.Errorf("error while reading structure (handle %d) contents: %w", structHdr.Handle, err)
		}
		// Read string-set
		for {
			str, err := table.ReadString(0x00)
			if err != nil {
				return nil, fmt.Errorf("error while reading string table (handle %d): %w", structHdr.Handle, err)
			}
			// Remove trailing null byte
			str = strings.TrimSuffix(str, "\x00")
			// Don't populate a zero-length first string if the string-set is
			// empty.
			if len(str) != 0 {
				s.Strings = append(s.Strings, str)
			}
			maybeTerminator, err := table.ReadByte()
			if err != nil {
				return nil, fmt.Errorf("error while reading string table (handle %d): %w", structHdr.Handle, err)
			}
			if maybeTerminator == 0 {
				// We have a valid string-set terminator, exit the loop
				break
			}
			// The next byte was not a terminator, put it back
			if err := table.UnreadByte(); err != nil {
				panic(err) // Cannot happen operationally
			}
		}
		switch structHdr.Type {
		case structTypeInactive:
			continue
		case structTypeBIOSInformation:
			var biosInfo BIOSInformationRaw
			if err := UnmarshalStructureRaw(s, &biosInfo); err != nil {
				return nil, fmt.Errorf("failed unmarshaling BIOS Information: %w", err)
			}
			tbl.BIOSInformationRaw = &biosInfo
		case structTypeSystemInformation:
			var systemInfo SystemInformationRaw
			if err := UnmarshalStructureRaw(s, &systemInfo); err != nil {
				return nil, fmt.Errorf("failed unmarshaling System Information: %w", err)
			}
			tbl.SystemInformationRaw = &systemInfo
		case structTypeBaseboardInformation:
			fmt.Println(s)
			var baseboardInfo BaseboardInformationRaw
			if err := UnmarshalStructureRaw(s, &baseboardInfo); err != nil {
				return nil, fmt.Errorf("failed unmarshaling Baseboard Information: %w", err)
			}
			tbl.BaseboardsInformationRaw = append(tbl.BaseboardsInformationRaw, &baseboardInfo)
		case structTypeSystemSlot:
			var sysSlot SystemSlotRaw
			if err := UnmarshalStructureRaw(s, &sysSlot); err != nil {
				return nil, fmt.Errorf("failed unmarshaling System Slot: %w", err)
			}
			tbl.SystemSlotsRaw = append(tbl.SystemSlotsRaw, &sysSlot)
		case structTypeMemoryDevice:
			var memoryDev MemoryDeviceRaw
			if err := UnmarshalStructureRaw(s, &memoryDev); err != nil {
				return nil, fmt.Errorf("failed unmarshaling Memory Device: %w", err)
			}
			tbl.MemoryDevicesRaw = append(tbl.MemoryDevicesRaw, &memoryDev)
		default:
			// Just pass through the raw structure
			tbl.Structures = append(tbl.Structures, s)
		}
	}
	return &tbl, nil
}

// Version contains a two-part version number consisting of a major and minor
// version. This is a common structure in SMBIOS.
type Version struct {
	Major uint8
	Minor uint8
}

func (v *Version) String() string {
	return fmt.Sprintf("%d.%d", v.Major, v.Minor)
}

// AtLeast returns true if the version in v is at least the given version.
func (v *Version) AtLeast(major, minor uint8) bool {
	return v.Major >= major && v.Minor >= minor
}

// UnmarshalStructureRaw unmarshals a SMBIOS structure into a Go struct which
// has some constraints. The first two fields need to be a `uint16 handle` and
// a `StructureVersion Version` field. After that any number of fields may
// follow as long as they are either of type `string` (which will be looked up
// in the string table) or readable by binary.Read. To determine the structure
// version, the smbios_min_vers struct tag needs to be put on the first field
// of a newer structure version. The version implicitly starts with 2.0.
// The version determined is written to the second target struct field.
// Fields which do not have a fixed size need to be typed as a slice and tagged
// with smbios_repeat set to the name of the field containing the count. The
// count field itself needs to be some width of uint.
func UnmarshalStructureRaw(rawStruct Structure, target any) error {
	v := reflect.ValueOf(target)
	if v.Kind() != reflect.Pointer {
		return errors.New("target needs to be a pointer")
	}
	v = v.Elem()
	if v.Kind() != reflect.Struct {
		return errors.New("target needs to be a pointer to a struct")
	}
	v.Field(0).SetUint(uint64(rawStruct.Handle))
	r := bytes.NewReader(rawStruct.FormattedSection)
	completedVersion := Version{Major: 0, Minor: 0}
	parsingVersion := Version{Major: 2, Minor: 0}
	numFields := v.NumField()
	hasAborted := false
	for i := 2; i < numFields; i++ {
		fieldType := v.Type().Field(i)
		if min := fieldType.Tag.Get("smbios_min_ver"); min != "" {
			var ver Version
			if _, err := fmt.Sscanf(min, "%d.%d", &ver.Major, &ver.Minor); err != nil {
				panic(fmt.Sprintf("invalid smbios_min_ver tag in %v: %v", fieldType.Name, err))
			}
			completedVersion = parsingVersion
			parsingVersion = ver
		}
		f := v.Field(i)

		if repeat := fieldType.Tag.Get("smbios_repeat"); repeat != "" {
			repeatCountField := v.FieldByName(repeat)
			if !repeatCountField.IsValid() {
				panic(fmt.Sprintf("invalid smbios_repeat tag in %v: no such field %q", fieldType.Name, repeat))
			}
			if !repeatCountField.CanUint() {
				panic(fmt.Sprintf("invalid smbios_repeat tag in %v: referenced field %q is not uint-compatible", fieldType.Name, repeat))
			}
			if f.Kind() != reflect.Slice {
				panic(fmt.Sprintf("cannot repeat a field (%q) which is not a slice", fieldType.Name))
			}
			if repeatCountField.Uint() > 65536 {
				return fmt.Errorf("refusing to read a field repeated more than 65536 times (given %d times)", repeatCountField.Uint())
			}
			repeatCount := int(repeatCountField.Uint())
			f.Set(reflect.MakeSlice(f.Type(), repeatCount, repeatCount))
			for j := 0; j < repeatCount; j++ {
				fs := f.Index(j)
				err := unmarshalField(&rawStruct, fs, r)
				if errors.Is(err, io.EOF) {
					hasAborted = true
					break
				} else if err != nil {
					return fmt.Errorf("error unmarshaling field %q: %w", fieldType.Name, err)
				}
			}
		}
		err := unmarshalField(&rawStruct, f, r)
		if errors.Is(err, io.EOF) {
			hasAborted = true
			break
		} else if err != nil {
			return fmt.Errorf("error unmarshaling field %q: %w", fieldType.Name, err)
		}
	}
	if !hasAborted {
		completedVersion = parsingVersion
	}
	if completedVersion.Major == 0 {
		return fmt.Errorf("structure's formatted section (%d bytes) is smaller than its minimal size", len(rawStruct.FormattedSection))
	}
	v.Field(1).Set(reflect.ValueOf(completedVersion))
	return nil
}

func unmarshalField(rawStruct *Structure, field reflect.Value, r *bytes.Reader) error {
	if field.Kind() == reflect.String {
		var stringTableIdx uint8
		err := binary.Read(r, binary.LittleEndian, &stringTableIdx)
		if err != nil {
			return err
		}
		if stringTableIdx == 0 {
			return nil
		}
		if int(stringTableIdx)-1 >= len(rawStruct.Strings) {
			return fmt.Errorf("string index (%d) bigger than string table (%q)", stringTableIdx-1, rawStruct.Strings)
		}
		field.SetString(rawStruct.Strings[stringTableIdx-1])
		return nil
	}
	return binary.Read(r, binary.LittleEndian, field.Addr().Interface())
}
