package base

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
)

const (
	procModulesPath = "/proc/modules"
	inContainerKey  = "ANYLINK_IN_CONTAINER"
	tunPath         = "/dev/net/tun"
)

var (
	InContainer = false
	modMap      = map[string]struct{}{}
)

func initMod() {
	container := os.Getenv(inContainerKey)
	if container == "true" {
		InContainer = true
	}
	log.Println("InContainer", InContainer)

	file, err := os.Open(procModulesPath)
	if err != nil {
		err = fmt.Errorf("[ERROR] Problem with open file: %s", err)
		panic(err)
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	for scanner.Scan() {
		splited := strings.Split(scanner.Text(), " ")
		if len(splited[0]) > 0 {
			modMap[splited[0]] = struct{}{}
		}
	}
}

func CheckModOrLoad(mod string) {
	log.Println("CheckModOrLoad", mod)

	if _, ok := modMap[mod]; ok {
		return
	}

	var err error

	if mod == "tun" || mod == "tap" {
		_, err = os.Stat(tunPath)
		if err == nil {
			// 文件存在
			return
		}
		// err = fmt.Errorf("[error] Linux tunFile is null %s", tunPath)
		// log.Println(err)
		// return
	}

	if InContainer {
		err = fmt.Errorf("[error] Linux module %s is not loaded, please run `modprobe %s`", mod, mod)
		log.Println(err)
		return
		// panic(err)
	}

	cmdstr := fmt.Sprintln("modprobe", mod)

	cmd := exec.Command("sh", "-c", cmdstr)
	b, err := cmd.CombinedOutput()
	if err != nil {
		log.Println(mod, string(b))
		panic(err)
	}
}