package routes

import (
	"net/http"

	//	"log"

	"ems.agt/features/aaaa"
	"ems.agt/features/cm"
	"ems.agt/features/dbrest"
	"ems.agt/features/file"
	"ems.agt/features/fm"
	"ems.agt/features/lm"
	"ems.agt/features/mml"
	"ems.agt/features/monitor/monitor"
	"ems.agt/features/monitor/psnet"
	"ems.agt/features/nbi"
	"ems.agt/features/pm"
	"ems.agt/features/security"
	"ems.agt/features/sm"
	"ems.agt/features/state"
	sysconfig "ems.agt/features/sys_config"
	sysdictdata "ems.agt/features/sys_dict_data"
	sysdicttype "ems.agt/features/sys_dict_type"
	sysmenu "ems.agt/features/sys_menu"
	sysrole "ems.agt/features/sys_role"
	sysuser "ems.agt/features/sys_user"
	"ems.agt/features/trace"
	udmuser "ems.agt/features/udm_user"
	"ems.agt/features/ue"
	"ems.agt/lib/midware"
	"ems.agt/lib/services"
	"ems.agt/src/framework/middleware/collectlogs"

	"github.com/gorilla/mux"
)

type Router struct {
	Method     string
	Pattern    string
	Handler    http.HandlerFunc
	Middleware mux.MiddlewareFunc
}

var routers []Router

func init() {
	Register("POST", security.UriOauthToken, security.LoginFromOMC, nil)
	Register("POST", security.UriOauthHandshake, security.HandshakeFromOMC, nil)
	Register("DELETE", security.UriOauthToken, security.LogoutFromOMC, nil)

	Register("POST", security.CustomUriOauthToken, security.LoginFromOMC, nil)
	Register("DELETE", security.CustomUriOauthToken, security.LogoutFromOMC, nil)
	Register("POST", security.CustomUriOauthHandshake, security.HandshakeFromOMC, nil)

	// System state
	Register("GET", state.UriSysState, state.GetStateFromNF, nil)
	Register("GET", state.UriSysState2, state.GetStateFromNF, nil)
	Register("GET", state.UriSysInfoAll, state.GetAllSysinfoFromNF, nil)
	Register("GET", state.UriSysInfoOne, state.GetOneSysinfoFromNF, nil)
	Register("GET", state.UriLicenseInfoAll, state.GetAllLicenseInfoFromNF, nil)
	Register("GET", state.UriLicenseInfoOne, state.GetOneLicenseInfoFromNF, nil)

	Register("GET", state.CustomUriSysState, state.GetStateFromNF, nil)
	Register("GET", state.CustomUriSysState2, state.GetStateFromNF, nil)
	Register("GET", state.CustomUriSysInfoAll, state.GetAllSysinfoFromNF, nil)
	Register("GET", state.CustomUriSysInfoOne, state.GetOneSysinfoFromNF, nil)
	Register("GET", state.CustomUriLicenseInfoAll, state.GetAllLicenseInfoFromNF, nil)
	Register("GET", state.CustomUriLicenseInfoOne, state.GetOneLicenseInfoFromNF, nil)

	Register("GET", sm.UriOMCLocalTime, sm.GetOMCLocalTime, nil)
	Register("GET", sm.CustomUriOMCLocalTime, sm.GetOMCLocalTime, nil)

	// 数据库直连操作权限
	selectPermission := midware.Authorize(map[string][]string{})
	updatePermission := midware.Authorize(map[string][]string{})
	insertPermission := midware.Authorize(map[string][]string{})
	deletePermission := midware.Authorize(map[string][]string{})

	// database management
	Register("GET", dbrest.XormGetDataUri, dbrest.DatabaseGetData, selectPermission)
	Register("GET", dbrest.XormSelectDataUri, dbrest.DatabaseGetData, selectPermission)
	Register("POST", dbrest.XormInsertDataUri, dbrest.DatabaseInsertData, insertPermission)
	Register("PUT", dbrest.XormUpdateDataUri, dbrest.DatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.XormDeleteDataUri, dbrest.DatabaseDeleteData, deletePermission)

	Register("GET", dbrest.CustomXormGetDataUri, dbrest.DatabaseGetData, selectPermission)
	Register("GET", dbrest.CustomXormSelectDataUri, dbrest.DatabaseGetData, selectPermission)
	Register("POST", dbrest.CustomXormInsertDataUri, dbrest.DatabaseInsertData, insertPermission)
	Register("PUT", dbrest.CustomXormUpdateDataUri, dbrest.DatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.CustomXormDeleteDataUri, dbrest.DatabaseDeleteData, deletePermission)

	Register("GET", dbrest.XormCommonUri, dbrest.DatabaseGetData, selectPermission)
	Register("POST", dbrest.XormCommonUri, dbrest.DatabaseInsertData, insertPermission)
	Register("PUT", dbrest.XormCommonUri, dbrest.DatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.XormCommonUri, dbrest.DatabaseDeleteData, deletePermission)

	Register("GET", dbrest.XormDatabaseUri, dbrest.TaskDatabaseGetData, selectPermission)
	Register("POST", dbrest.XormDatabaseUri, dbrest.TaskDatabaseInsertData, insertPermission)
	Register("PUT", dbrest.XormDatabaseUri, dbrest.TaskDatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.XormDatabaseUri, dbrest.TaskDatabaseDeleteData, deletePermission)

	Register("GET", dbrest.CustomXormCommonUri, dbrest.DatabaseGetData, selectPermission)
	Register("POST", dbrest.CustomXormCommonUri, dbrest.DatabaseInsertData, insertPermission)
	Register("PUT", dbrest.CustomXormCommonUri, dbrest.DatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.CustomXormCommonUri, dbrest.DatabaseDeleteData, deletePermission)

	Register("GET", dbrest.XormExtDataUri, dbrest.ExtDatabaseGetData, selectPermission)
	Register("POST", dbrest.XormExtDataUri, dbrest.ExtDatabaseInsertData, insertPermission)
	Register("PUT", dbrest.XormExtDataUri, dbrest.ExtDatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.XormExtDataUri, dbrest.ExtDatabaseDeleteData, deletePermission)

	Register("GET", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseGetData, selectPermission)
	Register("POST", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseInsertData, insertPermission)
	Register("PUT", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseUpdateData, updatePermission)
	Register("DELETE", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseDeleteData, deletePermission)

	// alarm restful Register
	Register("POST", fm.UriAlarms, fm.PostAlarmFromNF, nil)
	Register("Get", fm.UriAlarms, fm.GetAlarmFromNF, nil)

	Register("POST", fm.CustomUriAlarms, fm.PostAlarmFromNF, nil)
	Register("Get", fm.CustomUriAlarms, fm.GetAlarmFromNF, nil)

	// performance restful Register
	Register("POST", pm.PerformanceUri, pm.PostKPIReportFromNF, nil)
	Register("POST", pm.MeasureTaskUri, pm.PostMeasureTaskToNF, nil)
	Register("PUT", pm.MeasureTaskUri, pm.PutMeasureTaskToNF, nil)
	Register("DELETE", pm.MeasureTaskUri, pm.DeleteMeasureTaskToNF, nil)
	Register("PATCH", pm.MeasureTaskUri, pm.PatchMeasureTaskToNF, nil)
	Register("POST", pm.MeasureReportUri, pm.PostMeasureReportFromNF, nil)

	Register("POST", pm.MeasurementUri, pm.PostMeasurementFromNF, nil)
	Register("GET", pm.MeasurementUri, pm.GetMeasurementFromNF, nil)

	Register("POST", pm.CustomPerformanceUri, pm.PostKPIReportFromNF, nil)
	Register("POST", pm.CustomMeasureTaskUri, pm.PostMeasureTaskToNF, nil)
	Register("PUT", pm.CustomMeasureTaskUri, pm.PutMeasureTaskToNF, nil)
	Register("DELETE", pm.CustomMeasureTaskUri, pm.DeleteMeasureTaskToNF, nil)
	Register("PATCH", pm.CustomMeasureTaskUri, pm.PatchMeasureTaskToNF, nil)
	Register("POST", pm.CustomMeasureReportUri, pm.PostMeasureReportFromNF, nil)

	Register("POST", pm.CustomMeasurementUri, pm.PostMeasurementFromNF, nil)
	Register("GET", pm.CustomMeasurementUri, pm.GetMeasurementFromNF, nil)

	// parameter config management
	Register("GET", cm.ParamConfigUri, cm.GetParamConfigFromNF, nil)
	Register("POST", cm.ParamConfigUri, cm.PostParamConfigToNF, nil)
	Register("PUT", cm.ParamConfigUri, cm.PutParamConfigToNF, nil)
	Register("DELETE", cm.ParamConfigUri, cm.DeleteParamConfigToNF, nil)

	Register("GET", cm.CustomParamConfigUri, cm.GetParamConfigFromNF, nil)
	Register("POST", cm.CustomParamConfigUri, cm.PostParamConfigToNF, nil)
	Register("PUT", cm.CustomParamConfigUri, cm.PutParamConfigToNF, nil)
	Register("DELETE", cm.CustomParamConfigUri, cm.DeleteParamConfigToNF, nil)

	// Get/Create/Modify/Delete NE info
	Register("GET", cm.UriNeInfo, cm.GetNeInfo, nil)
	Register("POST", cm.UriNeInfo, cm.PostNeInfo, nil)
	Register("PUT", cm.UriNeInfo, cm.PutNeInfo, nil)
	Register("DELETE", cm.UriNeInfo, cm.DeleteNeInfo, nil)

	// Get/Create/Modify/Delete NE info
	Register("GET", cm.CustomUriNeInfo, cm.GetNeInfo, nil)
	Register("POST", cm.CustomUriNeInfo, cm.PostNeInfo, nil)
	Register("PUT", cm.CustomUriNeInfo, cm.PutNeInfo, nil)
	Register("DELETE", cm.CustomUriNeInfo, cm.DeleteNeInfo, nil)
	//ne service action handle
	Register("POST", cm.UriNeService, cm.PostNeServiceAction, nil)
	//ne service action handle
	Register("POST", cm.UriNeInstance, cm.PostNeInstanceAction, nil)
	// Post MML command to NF
	Register("POST", mml.UriMML, mml.PostMMLToNF, midware.LogMML)
	Register("POST", mml.UriMMLDiscard, mml.PostMMLToNF, nil)
	Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)

	Register("POST", mml.CustomUriMML, mml.PostMMLToNF, midware.LogMML)
	Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
	// Northbound Get NRM
	Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)

	Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)

	// Import/Export NF CM
	Register("GET", cm.NeCmUri, cm.ExportCmFromNF, nil)
	Register("POST", cm.NeCmUri, cm.ImportCmToNF, nil)

	Register("GET", cm.UriNeCmFile, cm.DownloadNeBackupFile, nil)
	Register("DELETE", cm.UriNeCmFile, cm.DeleteNeBackupFile, nil)

	Register("GET", cm.CustomNeCmUri, cm.ExportCmFromNF, nil)
	Register("POST", cm.CustomNeCmUri, cm.ImportCmToNF, nil)

	Register("GET", cm.CustomUriNeCmFile, cm.DownloadNeBackupFile, nil)
	Register("DELETE", cm.CustomUriNeCmFile, cm.DeleteNeBackupFile, nil)

	// Software management
	Register("GET", cm.UriSoftware, cm.DownloadSoftwareFile, nil)
	//Register("POST", cm.UriSoftware, cm.UploadSoftwareFile, nil)
	Register("POST", cm.UriSoftware, cm.UploadSoftwareMultiFile, nil)
	Register("DELETE", cm.UriSoftware, cm.DeleteSoftwareFile, nil)

	Register("POST", cm.UriSoftwareNE, cm.DistributeSoftwareToNF, nil)
	Register("PUT", cm.UriSoftwareNE, cm.ActiveSoftwareToNF, nil)
	Register("PATCH", cm.UriSoftwareNE, cm.RollBackSoftwareToNF, nil)

	Register("GET", cm.CustomUriSoftware, cm.DownloadSoftwareFile, nil)
	Register("POST", cm.CustomUriSoftware, cm.UploadSoftwareFile, nil)
	Register("DELETE", cm.CustomUriSoftware, cm.DeleteSoftwareFile, nil)

	Register("POST", cm.CustomUriSoftwareNE, cm.DistributeSoftwareToNF, nil)
	Register("PUT", cm.CustomUriSoftwareNE, cm.ActiveSoftwareToNF, nil)
	Register("PATCH", cm.CustomUriSoftwareNE, cm.RollBackSoftwareToNF, nil)

	// License management
	Register("POST", cm.UriLicense, cm.UploadLicenseFileData, nil)
	Register("POST", cm.UriLicenseExt, cm.UploadLicenseFileData, nil)

	Register("POST", cm.CustomUriLicense, cm.UploadLicenseFileData, nil)
	Register("POST", cm.CustomUriLicenseExt, cm.UploadLicenseFileData, nil)

	// Trace management 跟踪任务
	Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_INSERT)))
	Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_UPDATE)))
	Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_DELETE)))
	Register("GET", trace.UriTraceDecMsg, trace.ParseRawMsg2Html, nil)

	Register("POST", trace.CustomUriTraceTask, trace.PostTraceTaskToNF, nil)
	Register("PUT", trace.CustomUriTraceTask, trace.PutTraceTaskToNF, nil)
	Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)

	// 网元发送执行 pcap抓包任务
	Register("POST", trace.UriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_INSERT)))
	Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_INSERT)))
	// 网元发送执行 抓包下载pcap文件
	Register("POST", trace.UriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_EXPORT)))
	Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_EXPORT)))
	// 网元发送执行UPF pcap抓包
	Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_INSERT)))
	Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet capturing task", collectlogs.BUSINESS_TYPE_INSERT)))

	// file management
	Register("POST", file.UriFile, file.UploadFile, nil)
	Register("GET", file.UriFile, file.DownloadFile, nil)
	Register("DELETE", file.UriFile, file.DeleteFile, nil)

	Register("POST", file.CustomUriFile, file.UploadFile, nil)
	Register("GET", file.CustomUriFile, file.DownloadFile, nil)
	Register("DELETE", file.CustomUriFile, file.DeleteFile, nil)

	// AAAA
	Register("GET", aaaa.UriAAAASSO, aaaa.GetSSOFromAAAA, nil)
	// AAAA
	Register("GET", aaaa.CustomUriAAAASSO, aaaa.GetSSOFromAAAA, nil)

	// UEInfo
	Register("GET", ue.UriUEInfo, ue.GetUEInfoFromNF, nil)
	Register("GET", ue.CustomUriUEInfo, ue.GetUEInfoFromNF, nil)

	// UEInfo
	Register("GET", ue.UriUENum, ue.GetUENumFromNF, nil)
	Register("GET", ue.CustomUriUENum, ue.GetUENumFromNF, nil)

	// NBInfo
	Register("GET", ue.UriNBInfo, ue.GetNBInfoFromNF, nil)
	Register("GET", ue.CustomUriNBInfo, ue.GetNBInfoFromNF, nil)

	// 进程网络
	Register("GET", psnet.UriWs, psnet.ProcessWs, nil)
	Register("POST", psnet.UriStop, psnet.StopProcess, nil)
	Register("POST", psnet.UriPing, psnet.Ping, nil)

	// 主机CPU内存监控
	Register("POST", monitor.UriLoad, monitor.LoadMonitor, nil)
	Register("GET", monitor.UriNetOpt, monitor.Netoptions, nil)
	Register("GET", monitor.UriIPAddr, monitor.IPAddr, nil)
	Register("GET", monitor.UriIoOpt, monitor.Iooptions, nil)

	// 文件资源
	Register("GET", file.UriDiskList, file.DiskList, nil)
	Register("POST", file.UriListFiles, file.ListFiles, nil)

	// 数据库连接情况
	Register("GET", dbrest.UriDbConnection, dbrest.DbConnection, nil)
	Register("GET", dbrest.CustomUriDbConnection, dbrest.DbConnection, nil)
	Register("POST", dbrest.UriDbStop, dbrest.DbStop, nil)
	Register("POST", dbrest.CustomUriDbStop, dbrest.DbStop, nil)

	// 系统备份
	Register("POST", dbrest.UriDbBackup, dbrest.DbBackup, nil)
	Register("POST", dbrest.CustomUriDbBackup, dbrest.DbBackup, nil)
	Register("POST", dbrest.UriConfBackup, dbrest.ConfBackup, nil)
	Register("POST", dbrest.CustomUriConfBackup, dbrest.ConfBackup, nil)

	// 日志表备份
	Register("POST", lm.ExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
	Register("POST", lm.CustomExtBackupDataUri, lm.ExtDatabaseBackupData, nil)

	// 系统登录
	Register("POST", security.UriLogin, security.LoginOMC, nil)
	Register("POST", security.CustomUriLogin, security.LoginOMC, nil)

	// 获取验证码
	Register("GET", security.UriCaptchaImage, security.CaptchaImage, nil)
	Register("GET", security.CustomUriCaptchaImage, security.CaptchaImage, nil)

	// 登录用户信息
	Register("GET", security.UriUserInfo, security.UserInfo, midware.Authorize(nil))
	Register("GET", security.CustomUriUserInfo, security.UserInfo, midware.Authorize(nil))

	// 登录用户路由信息
	Register("GET", security.UriRouters, security.Routers, midware.Authorize(nil))
	Register("GET", security.CustomUriRouters, security.Routers, midware.Authorize(nil))

	// 参数配置信息接口添加到路由
	for _, v := range sysconfig.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// 字典类型信息接口添加到路由
	for _, v := range sysdicttype.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// 字典类型对应的字典数据信息接口添加到路由
	for _, v := range sysdictdata.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// 菜单接口添加到路由
	for _, v := range sysmenu.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// 角色接口添加到路由
	for _, v := range sysrole.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// 用户接口添加到路由
	for _, v := range sysuser.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}

	// UDM 用户信息接口添加到路由
	for _, v := range udmuser.Routers() {
		Register(v.Method, v.Pattern, v.Handler, v.Middleware)
	}
}

// To resolv rest POST/PUT/DELETE/PATCH cross domain
func OptionsProc(w http.ResponseWriter, r *http.Request) {
	services.ResponseStatusOK204NoContent(w)
}

func NewRouter() *mux.Router {
	r := mux.NewRouter()

	// set custom handle for status 404/405
	// r.NotFoundHandler = services.CustomResponseNotFound404Handler()
	// r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()

	r.Use(midware.LoggerTrace)
	// r.Use(midware.Cors)
	// r.Use(midware.OptionProcess)
	// r.Use(midware.ArrowIPAddr)

	for _, router := range routers {
		rt := r.Methods(router.Method).Subrouter()
		rt.HandleFunc(router.Pattern, router.Handler)
		if router.Middleware != nil {
			rt.Use(router.Middleware)
		}

	}

	return r
}

func Register(method, pattern string, handler http.HandlerFunc, middleware mux.MiddlewareFunc) {
	routers = append(routers, Router{method, pattern, handler, middleware})
}
