package kmod

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"golang.org/x/sys/unix"
	"google.golang.org/protobuf/proto"

	kmodpb "source.monogon.dev/osbase/kmod/spec"
)

// Manager contains all the logic and metadata required to efficiently load
// Linux kernel modules. It has internal loading tracking, thus it's recommended
// to only keep one Manager instance running per kernel. It can recreate its
// internal state quite well, but there are edge cases where the kernel makes
// it hard to do so (MODULE_STATE_UNFORMED) thus if possible that single
// instance should be kept alive. It currently does not support unloading
// modules, but that can be added to the existing design if deemed necessary.
type Manager struct {
	// Directory the modules are loaded from. The path in each module Meta
	// message is relative to this.
	modulesPath string
	meta        *kmodpb.Meta
	// Extra map to quickly find module indexes from names
	moduleIndexes map[string]uint32

	// mutex protects loadedModules, rest is read-only
	// This cannot use a RWMutex as locks cannot be upgraded
	mutex         sync.Mutex
	loadedModules map[uint32]bool
}

// NewManager instantiates a kernel module loading manager. Please take a look
// at the additional considerations on the Manager type itself.
func NewManager(meta *kmodpb.Meta, modulesPath string) (*Manager, error) {
	modIndexes := make(map[string]uint32)
	for i, m := range meta.Modules {
		modIndexes[m.Name] = uint32(i)
	}
	modulesFile, err := os.Open("/proc/modules")
	if err != nil {
		return nil, err
	}
	loadedModules := make(map[uint32]bool)
	s := bufio.NewScanner(modulesFile)
	for s.Scan() {
		fields := strings.Fields(s.Text())
		if len(fields) == 0 {
			// Skip invalid lines
			continue
		}
		modIdx, ok := modIndexes[fields[0]]
		if !ok {
			// Certain modules are only available as built-in and are thus not
			// part of the module metadata. They do not need to be handled by
			// this code, ignore them.
			continue
		}
		loadedModules[modIdx] = true
	}
	return &Manager{
		modulesPath:   modulesPath,
		meta:          meta,
		moduleIndexes: modIndexes,
		loadedModules: loadedModules,
	}, nil
}

// NewManagerFromPath instantiates a new kernel module loading manager from a
// path containing a meta.pb file containing a kmod.Meta message as well as the
// kernel modules within. Please take a look at the additional considerations on
// the Manager type itself.
func NewManagerFromPath(modulesPath string) (*Manager, error) {
	moduleMetaRaw, err := os.ReadFile(filepath.Join(modulesPath, "meta.pb"))
	if err != nil {
		return nil, fmt.Errorf("error reading module metadata: %w", err)
	}
	var moduleMeta kmodpb.Meta
	if err := proto.Unmarshal(moduleMetaRaw, &moduleMeta); err != nil {
		return nil, fmt.Errorf("error decoding module metadata: %w", err)
	}
	return NewManager(&moduleMeta, modulesPath)
}

// ErrNotFound is returned when an attempt is made to load a module which does
// not exist according to the loaded metadata.
type ErrNotFound struct {
	Name string
}

func (e *ErrNotFound) Error() string {
	return fmt.Sprintf("module %q does not exist", e.Name)
}

// LoadModule loads the module with the given name. If the module is already
// loaded or  built-in, it returns no error. If it failed loading the module or
// the module does not exist, it returns an error.
func (s *Manager) LoadModule(name string) error {
	modIdx, ok := s.moduleIndexes[name]
	if !ok {
		return &ErrNotFound{Name: name}
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.loadModuleRecursive(modIdx)
}

// LoadModulesForDevice loads all modules whose device match expressions
// (modaliases) match the given device modalias. It only returns an error if
// a module which matched the device or one of its dependencies caused an error
// when loading. A device modalias string which matches nothing is not an error.
func (s *Manager) LoadModulesForDevice(devModalias string) error {
	matches := make(map[uint32]bool)
	lookupModulesRec(s.meta.ModuleDeviceMatches, devModalias, matches)
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for m := range matches {
		if err := s.loadModuleRecursive(m); err != nil {
			return err
		}
	}
	return nil
}

// Caller is REQUIRED to hold s.mutex!
func (s *Manager) loadModuleRecursive(modIdx uint32) error {
	if s.loadedModules[modIdx] {
		return nil
	}
	modMeta := s.meta.Modules[modIdx]
	if modMeta.Path == "" {
		// Module is built-in, dependency always satisfied
		return nil
	}
	for _, dep := range modMeta.Depends {
		if err := s.loadModuleRecursive(dep); err != nil {
			// Pass though as is, recursion can otherwise cause
			// extremely large errors
			return err
		}
	}
	module, err := os.Open(filepath.Join(s.modulesPath, modMeta.Path))
	if err != nil {
		return fmt.Errorf("error opening kernel module: %w", err)
	}
	defer module.Close()
	err = LoadModule(module, "", 0)
	if err != nil && errors.Is(err, unix.EEXIST) {
		return fmt.Errorf("error loading kernel module %v: %w", modMeta.Name, err)
	}
	s.loadedModules[modIdx] = true
	return nil
}
