/*
 * @description:web项目启动
 * @Author: CP
 * @Date: 2020-08-21 11:20:00
 * @FilePath: \construction_management\bootstrap\bootstrap.go
 */
package bootstrap

import (
	"time"

	"github.com/iris-contrib/middleware/csrf"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/middleware/logger"
	"github.com/kataras/iris/v12/middleware/recover"
	"go.mod/conf"
)

//配置器，定制化的配置--方法类型
type Configurator func(*Bootstrapper)

//GCJSXM88CP20200902666A477C084477
// const csrfKey = "GCJSXM88CP20200902666A477C084477"

//结构体扩展iris，类此于继承
type Bootstrapper struct {
	*iris.Application
	AppName      string
	AppOwner     string
	AppSpawnDate time.Time
}

//var RpcConnect *grpc.ClientConn
func init() {
	// log.Println("RpcConnect 初始化中...")
	// conn, err := grpc.Dial(conf.NodeRpcHost, grpc.WithInsecure())
	// if err != nil {
	// 	log.Fatalf("did not connect: %v", err)
	// }
	// RpcConnect = conn
	// log.Println("RpcConnect 初始化成功")
}

//新建和返回一个Bootstrapper
func New(appName, appOwner string, cfgs ...Configurator) *Bootstrapper {
	b := &Bootstrapper{
		AppName:      appName,
		AppOwner:     appOwner,
		AppSpawnDate: time.Now(),
		Application:  iris.New(),
	}

	//数组遍历 cfg方法
	for _, cfg := range cfgs {
		cfg(b)
	}

	return b
}

//Bootstrapper的方法 读取模板
func (b *Bootstrapper) SetupViews(viewsDir string) {
	htmlEngine := iris.HTML(viewsDir, ".html").Layout("shared/layout.html")
	// 每次重新加载模版（线上关闭它）
	htmlEngine.Reload(true)
	// 给模版内置各种定制的方法
	htmlEngine.AddFunc("FromUnixtimeShort", func(t int) string {
		dt := time.Unix(int64(t), int64(0))
		return dt.Format(conf.SysTimeformShort)
	})
	htmlEngine.AddFunc("FromUnixtime", func(t int) string {
		dt := time.Unix(int64(t), int64(0))
		return dt.Format(conf.SysTimeform)
	})
	b.RegisterView(htmlEngine)
}

// 配置csrf
func (b *Bootstrapper) SetupCsrfHandlers(csrfKey string) {
	protect := csrf.Protect([]byte(csrfKey), csrf.FieldName("csrf"), csrf.Secure(false), csrf.Path("/"), csrf.ErrorHandler(func(ctx iris.Context) {
		ctx.JSON(iris.Map{"code": -1, "msg": "CSRF token invalid"})
	}))
	//csrf.Domain("")

	// , csrf.Domain("cmr.com"), csrf.Path("/")
	b.Party("/", protect)
}

// 配置jwt
// func (b *Bootstrapper) SetupJwtHandlers(jwtKey string) {

// j2 := jwt.New(jwt.Config{
// 	// 注意，新增了一个错误处理函数
// 	ErrorHandler: func(ctx iris.Context, err error) {
// 		if err == nil {
// 			return
// 		}

// 		ctx.StopExecution()
// 		ctx.StatusCode(iris.StatusUnauthorized)
// 		ctx.JSON(ResModel{
// 			Code: "501",
// 			Msg:  err.Error(),
// 		})
// 	},
// 	// 设置一个函数返回秘钥，关键在于return []byte("这里设置秘钥")
// 	ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
// 		return []byte(jwtKey), nil
// 	},

// 	// 设置一个加密方法
// 	SigningMethod: jwt.SigningMethodHS256,
// })

// 	//b.Party("/", j2.Serve)
// }

// 装配rpcClient
func (b *Bootstrapper) SetupRpcClient() {
	// b.Use(func(ctx iris.Context) {
	// 	ctx.Values().Set("RpcConnect", RpcConnect)
	// 	ctx.Next()
	// })
	// log.Println("RpcConnect 注入成功")
}

//处理异常--设置错误信息展示
func (b *Bootstrapper) SetupErrorHandlers() {
	b.OnAnyErrorCode(func(ctx iris.Context) {
		// err := iris.Map{
		// 	"app":     b.AppName,
		// 	"status":  ctx.GetStatusCode(),
		// 	"message": ctx.Values().GetString("message"),
		// }
		//如果是json格式，使用json方式输出
		// if jsonOutput := ctx.URLParamExists("json"); jsonOutput {
		// 	ctx.JSON(err)
		// 	return
		// }

		// ctx.ViewData("Err", err)
		// ctx.ViewData("Title", "Error")
		// ctx.View("shared/error.html")

		ctx.JSON(iris.Map{"code": -1, "msg": "请求错误，请检查"})

	})
}

//配置的方法 Configure accepts configurations and runs them inside the Bootstraper's context.
func (b *Bootstrapper) Configure(cs ...Configurator) {
	for _, c := range cs {
		c(b)
	}
}

// 启动计划任务服务
func (b *Bootstrapper) setupCron() {
	// TODO
}

const (
	StaticAssets = "./public"
	Favicon      = "/favicon.ico"
	//20200902GCJSXM7C084477AEA06096F5
	//9AB0F421E53A477C084477AEA06096F5
	CsrfKey = "9AB0F421E53A477C084477AEA06096F5"
	JwtKey  = "9AB0F421E53A477C084477AEA06096F5"
)

// 初始化Bootstrap
// Returns itself.
func (b *Bootstrapper) Bootstrap() *Bootstrapper {
	//设置模板
	//b.SetupViews("./views")
	// b.SetupSessions(24*time.Hour,
	// 	[]byte("the-big-and-secret-fash-key-here"),
	// 	[]byte("lot-secret-of-characters-big-too"),
	// )
	// 设置csrf
	b.SetupCsrfHandlers(CsrfKey)
	// 设置jwt
	//b.SetupJwtHandlers(JwtKey)
	// 设置rpc
	//b.SetupRpcClient()
	//设置异常信息
	b.SetupErrorHandlers()

	// static files
	//b.Favicon(StaticAssets + Favicon)
	//b.StaticWeb(StaticAssets[1:], StaticAssets)
	b.HandleDir(StaticAssets[1:], iris.Dir(StaticAssets))
	b.HandleDir("/docs", iris.Dir("./docs"))
	// indexHtml, err := ioutil.ReadFile(StaticAssets + "/index.html")
	// if err == nil {
	// 	b.StaticContent(StaticAssets[1:]+"/", "text/html",
	// 		indexHtml)
	// }
	// 不要把目录末尾"/"省略掉
	//iris.WithoutPathCorrectionRedirection(b.Application)

	// crontab
	b.setupCron()

	// middleware, after static files
	b.Use(recover.New())
	b.Use(logger.New())

	return b
}

func (b *Bootstrapper) Listen(addr string, cfgs ...iris.Configurator) {
	b.Run(iris.Addr(addr), cfgs...)
}
