// Package tool.RuntimeCaller 函数调用路径信息
package tool

import (
	"log"
	"os"
	"path"
	"runtime"
	"strings"

	"go.uber.org/zap"
)

type callFunc struct {
	Name    string
	Path    string
	Package string
	Line    int
}

type RuntimeCaller struct {
	ProjectPath string
	CallFunc    callFunc
}

func NewCurrentCaller() *RuntimeCaller {
	dir, err := os.Getwd()
	if err != nil {
		log.Fatal("tool.NewCurrentCaller获取当前目录失败", zap.Error(err))
	}
	if runtime.GOOS == "windows" {
		dir = strings.ReplaceAll(dir, "\\", "/")
	}

	caller := &RuntimeCaller{
		ProjectPath: path.Dir(path.Dir(dir)),
	}

	return caller.Init(1)
}

func (c *RuntimeCaller) Init(depth int) *RuntimeCaller {
	pc, file, line, ok := runtime.Caller(depth + 2)
	if !ok {
		log.Println("tool.RuntimeCaller.Init获取调用者失败")
		return c
	}

	relativePath := strings.ReplaceAll(file, c.ProjectPath, "")
	callFuncName := strings.Split(runtime.FuncForPC(pc).Name(), ".")
	c.CallFunc = callFunc{
		Name:    callFuncName[len(callFuncName)-1],
		Path:    strings.TrimLeft(relativePath, "/"),
		Package: strings.Join(callFuncName[:len(callFuncName)-1], "."),
		Line:    line,
	}

	return c
}
