func (eng *Engine) ClonedBySetter(setter Setter) *Engine {
	setter(eng)
	return eng
}
ClonedBySetter copy a new Engine by a setter callback function.
package engine
import (
	"bytes"
	"encoding/json"
	errors2 "errors"
	"fmt"
	template2 "html/template"
	"net/http"
	"runtime/debug"
	"strings"
	"sync"
	"github.com/GoAdminGroup/go-admin/modules/language"
	"github.com/GoAdminGroup/go-admin/template/icon"
	"github.com/GoAdminGroup/go-admin/template/types/action"
	"github.com/GoAdminGroup/go-admin/adapter"
	"github.com/GoAdminGroup/go-admin/context"
	"github.com/GoAdminGroup/go-admin/modules/auth"
	"github.com/GoAdminGroup/go-admin/modules/config"
	"github.com/GoAdminGroup/go-admin/modules/db"
	"github.com/GoAdminGroup/go-admin/modules/errors"
	"github.com/GoAdminGroup/go-admin/modules/logger"
	"github.com/GoAdminGroup/go-admin/modules/menu"
	"github.com/GoAdminGroup/go-admin/modules/service"
	"github.com/GoAdminGroup/go-admin/modules/system"
	"github.com/GoAdminGroup/go-admin/modules/ui"
	"github.com/GoAdminGroup/go-admin/plugins"
	"github.com/GoAdminGroup/go-admin/plugins/admin"
	"github.com/GoAdminGroup/go-admin/plugins/admin/models"
	"github.com/GoAdminGroup/go-admin/plugins/admin/modules/response"
	"github.com/GoAdminGroup/go-admin/plugins/admin/modules/table"
	"github.com/GoAdminGroup/go-admin/template"
	"github.com/GoAdminGroup/go-admin/template/types"
)
type Engine struct {
	PluginList   plugins.Plugins
	Adapter      adapter.WebFrameWork
	Services     service.List
	NavButtons   *types.Buttons
	config       *config.Config
	announceLock sync.Once
}
func Default() *Engine {
	engine = &Engine{
		Adapter:    defaultAdapter,
		Services:   service.GetServices(),
		NavButtons: new(types.Buttons),
	}
	return engine
}
func (eng *Engine) Use(router interface{}) error {
	if eng.Adapter == nil {
		emptyAdapterPanic()
	}
	eng.Services.Add(auth.InitCSRFTokenSrv(eng.DefaultConnection()))
	eng.initSiteSetting()
	eng.initJumpNavButtons()
	eng.initPlugins()
	printInitMsg(language.Get("initialize success"))
	return eng.Adapter.Use(router, eng.PluginList)
}
func (eng *Engine) AddPlugins(plugs ...plugins.Plugin) *Engine {
	if len(plugs) == 0 {
		return eng
	}
	for _, plug := range plugs {
		eng.PluginList = eng.PluginList.Add(plug)
	}
	return eng
}
func (eng *Engine) AddPluginList(plugs plugins.Plugins) *Engine {
	if len(plugs) == 0 {
		return eng
	}
	for _, plug := range plugs {
		eng.PluginList = eng.PluginList.Add(plug)
	}
	return eng
}
func (eng *Engine) FindPluginByName(name string) (plugins.Plugin, bool) {
	for _, plug := range eng.PluginList {
		if plug.Name() == name {
			return plug, true
		}
	}
	return nil, false
}
func (eng *Engine) AddAuthService(processor auth.Processor) *Engine {
	eng.Services.Add("auth", auth.NewService(processor))
	return eng
}
func (eng *Engine) announce() *Engine {
	if eng.config.Debug {
		eng.announceLock.Do(func() {
			fmt.Printf(language.Get("goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n"))
		})
	}
	return eng
}
func (eng *Engine) AddConfig(cfg *config.Config) *Engine {
	return eng.setConfig(cfg).announce().initDatabase()
}
func (eng *Engine) setConfig(cfg *config.Config) *Engine {
	eng.config = config.Initialize(cfg)
	sysCheck, themeCheck := template.CheckRequirements()
	if !sysCheck {
		logger.Panicf(language.Get("wrong goadmin version, theme %s required goadmin version are %s"),
			eng.config.Theme, strings.Join(template.Default().GetRequirements(), ","))
	}
	if !themeCheck {
		logger.Panicf(language.Get("wrong theme version, goadmin %s required version of theme %s is %s"),
			system.Version(), eng.config.Theme, strings.Join(system.RequireThemeVersion()[eng.config.Theme], ","))
	}
	return eng
}
func (eng *Engine) AddConfigFromJSON(path string) *Engine {
	cfg := config.ReadFromJson(path)
	return eng.setConfig(&cfg).announce().initDatabase()
}
func (eng *Engine) AddConfigFromYAML(path string) *Engine {
	cfg := config.ReadFromYaml(path)
	return eng.setConfig(&cfg).announce().initDatabase()
}
func (eng *Engine) AddConfigFromINI(path string) *Engine {
	cfg := config.ReadFromINI(path)
	return eng.setConfig(&cfg).announce().initDatabase()
}
func (eng *Engine) initDatabase() *Engine {
	printInitMsg(language.Get("initialize database connections"))
	for driver, databaseCfg := range eng.config.Databases.GroupByDriver() {
		eng.Services.Add(driver, db.GetConnectionByDriver(driver).InitDB(databaseCfg))
	}
	if defaultAdapter == nil {
		emptyAdapterPanic()
	}
	defaultConnection := db.GetConnection(eng.Services)
	defaultAdapter.SetConnection(defaultConnection)
	eng.Adapter.SetConnection(defaultConnection)
	return eng
}
func (eng *Engine) AddAdapter(ada adapter.WebFrameWork) *Engine {
	eng.Adapter = ada
	defaultAdapter = ada
	return eng
}
var defaultAdapter adapter.WebFrameWork
var engine *Engine
var navButtons = new(types.Buttons)
func emptyAdapterPanic() {
	logger.Panic(language.Get("adapter is nil, import the default adapter or use addadapter method add the adapter"))
}
func Register(ada adapter.WebFrameWork) {
	if ada == nil {
		emptyAdapterPanic()
	}
	defaultAdapter = ada
}
func User(ctx interface{}) (models.UserModel, bool) {
	return defaultAdapter.User(ctx)
}
func (eng *Engine) User(ctx interface{}) (models.UserModel, bool) {
	return eng.Adapter.User(ctx)
}
func (eng *Engine) DB(driver string) db.Connection {
	return db.GetConnectionFromService(eng.Services.Get(driver))
}
func (eng *Engine) DefaultConnection() db.Connection {
	return eng.DB(eng.config.Databases.GetDefault().Driver)
}
func (eng *Engine) MysqlConnection() db.Connection {
	return db.GetConnectionFromService(eng.Services.Get(db.DriverMysql))
}
func (eng *Engine) MssqlConnection() db.Connection {
	return db.GetConnectionFromService(eng.Services.Get(db.DriverMssql))
}
func (eng *Engine) PostgresqlConnection() db.Connection {
	return db.GetConnectionFromService(eng.Services.Get(db.DriverPostgresql))
}
func (eng *Engine) SqliteConnection() db.Connection {
	return db.GetConnectionFromService(eng.Services.Get(db.DriverSqlite))
}
type ConnectionSetter func(db.Connection)
func (eng *Engine) ResolveConnection(setter ConnectionSetter, driver string) *Engine {
	setter(eng.DB(driver))
	return eng
}
func (eng *Engine) ResolveMysqlConnection(setter ConnectionSetter) *Engine {
	eng.ResolveConnection(setter, db.DriverMysql)
	return eng
}
func (eng *Engine) ResolveMssqlConnection(setter ConnectionSetter) *Engine {
	eng.ResolveConnection(setter, db.DriverMssql)
	return eng
}
func (eng *Engine) ResolveSqliteConnection(setter ConnectionSetter) *Engine {
	eng.ResolveConnection(setter, db.DriverSqlite)
	return eng
}
func (eng *Engine) ResolvePostgresqlConnection(setter ConnectionSetter) *Engine {
	eng.ResolveConnection(setter, db.DriverPostgresql)
	return eng
}
type Setter func(*Engine)
func (eng *Engine) Clone(e *Engine) *Engine {
	e = eng
	return eng
}