package main

// #include <dlfcn.h>
// #include <stdlib.h> // for free
// #include "caller.h"
// #cgo LDFLAGS: -ldl
import "C"

import (
	"log"
	"path/filepath"
	"time"
	"unsafe"
)

// Loop trough the plugin path to load any .so
func main() {
	for {
		matches, err := filepath.Glob("plugins/bin/*.so")
		panicIfErr(err)
		for _, v := range matches {
			execPlugin(v)

		}
		<-time.After(3 * time.Second)
	}
}

func execPlugin(plugpath string) {
	defer func() {
		if q := recover(); q != nil {
			log.Println("Recovering panic")
		}
	}()

	plugname := C.CString(plugpath)
	phandle := C.dlopen(plugname, C.RTLD_NOW) // Win32 LoadLibrary
	if phandle == nil {
		cerr := C.dlerror()
		log.Println("err:", C.GoString(cerr))
		C.free(unsafe.Pointer(cerr))
	}
	C.free(unsafe.Pointer(plugname))

	cs := C.CString("Add")
	// Find our Add implementation
	sym := C.dlsym(phandle, cs)
	C.free(unsafe.Pointer(cs))

	if sym == nil { // Not thread safe since is fetching error after call (another dl might be called in between)
		cerr := C.dlerror()
		log.Println("err:", C.GoString(cerr))
		C.free(unsafe.Pointer(cerr))
	}

	r := C.call(sym, 1, 2)
	res := C.GoString(r)
	log.Printf("From: %-30s Result --> '%s'", plugpath, res)
	C.free(unsafe.Pointer(r))

	//log.Println("Res:", C.GoString(C.testLocal())) /**/

	C.dlclose(phandle)

}

func panicIfErr(err error) {
	if err != nil {
		panic(err)
	}
}
