// Package try...
//
// Description : 各种接口定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-07-24 9:47 下午
package try

import (
	"encoding/json"
	"fmt"
	"runtime"

	"git.zhangdeman.cn/zhangdeman/gopkg/easymap"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
)

// ICatchHandler catch处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:12 下午 2021/7/24
type ICatchHandler interface {
	Catch(e error, handler func(err error)) ICatchHandler
	CatchAll(handler func(err error)) FinalHandler
	FinalHandler
}

// SystemError 系统异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:35 下午 2021/7/24
type SystemError struct {
	error
}

// FinalHandler final处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:12 下午 2021/7/24
type FinalHandler interface {
	Finally(handlers ...func())
}

// WithNormal 入口try函数, 普通的逻辑
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:43 下午 2021/7/24
func WithNormal(f func()) ICatchHandler {
	t := &CatchHandler{}
	defer func() {
		defer func() {
			r := recover()
			if r != nil {
				switch r.(type) {
				case runtime.Error:
					t.err = r.(error)
				case error:
					t.err = r.(error)
				case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
					t.err = SystemError{SystemError{error: errors.New(fmt.Sprintf("%v", r))}}
				default:
					byteData, _ := json.Marshal(r)
					t.err = SystemError{error: errors.New(string(byteData))}
				}
			}
		}()
		f()
	}()
	return t
}

// WithGin 带 gin context 的 try, 可集成gin框架
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:50 下午 2021/7/24
func WithGin(ctx *gin.Context, f func(ctx *gin.Context)) ICatchHandler {
	t := &CatchHandler{}
	defer func() {
		defer func() {
			r := recover()
			t.err = r.(error)
		}()
		f(ctx)
	}()
	return t
}

// WithData 带数据的try
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:52 下午 2021/7/24
func WithData(data easymap.EasyMap, f func(data easymap.EasyMap)) ICatchHandler {
	t := &CatchHandler{}
	defer func() {
		defer func() {
			r := recover()
			if r != nil {
				t.err = r.(error)
			}
		}()
		f(data)
	}()
	return t
}

// WithInterface 传入任意数据类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:53 下午 2021/7/24
func WithInterface(data interface{}, f func(data interface{})) ICatchHandler {
	t := &CatchHandler{}
	defer func() {
		defer func() {
			r := recover()
			if r != nil {
				t.err = r.(error)
			}
		}()
		f(data)
	}()
	return t
}