/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package utils

import (
	"fmt"
	"runtime"
	"strings"
)

// RecoverToError call the recover to catch the panic and changed it to be an error
func RecoverToError() error {
	if r := recover(); r != nil {
		switch e := r.(type) {
		case error:
			return e
		case string:
			return fmt.Errorf("%s", e)
		default:
			return fmt.Errorf("%v", e)
		}
	}
	return nil
}

// GatherCallFrames FIXME ...
func GatherCallFrames(delta int) string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3+delta, pc[:])
	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}
