package fiber

import (
	
)

// OnRouteHandler Handlers define a function to create hooks for Fiber.
type (
	OnRouteHandler     = func(Route) error
	OnNameHandler      = OnRouteHandler
	OnGroupHandler     = func(Group) error
	OnGroupNameHandler = OnGroupHandler
	OnListenHandler    = func(ListenData) error
	OnShutdownHandler  = func() error
	OnForkHandler      = func(int) error
	OnMountHandler     = func(*App) error
)

// Hooks is a struct to use it with App.
type Hooks struct {
	// Embed app
	app *App

	// Hooks
	onRoute     []OnRouteHandler
	onName      []OnNameHandler
	onGroup     []OnGroupHandler
	onGroupName []OnGroupNameHandler
	onListen    []OnListenHandler
	onShutdown  []OnShutdownHandler
	onFork      []OnForkHandler
	onMount     []OnMountHandler
}

// ListenData is a struct to use it with OnListenHandler
type ListenData struct {
	Host string
	Port string
	TLS  bool
}

func newHooks( *App) *Hooks {
	return &Hooks{
		app:         ,
		onRoute:     make([]OnRouteHandler, 0),
		onGroup:     make([]OnGroupHandler, 0),
		onGroupName: make([]OnGroupNameHandler, 0),
		onName:      make([]OnNameHandler, 0),
		onListen:    make([]OnListenHandler, 0),
		onShutdown:  make([]OnShutdownHandler, 0),
		onFork:      make([]OnForkHandler, 0),
		onMount:     make([]OnMountHandler, 0),
	}
}

// OnRoute is a hook to execute user functions on each route registeration.
// Also you can get route properties by route parameter.
func ( *Hooks) ( ...OnRouteHandler) {
	.app.mutex.Lock()
	.onRoute = append(.onRoute, ...)
	.app.mutex.Unlock()
}

// OnName is a hook to execute user functions on each route naming.
// Also you can get route properties by route parameter.
//
// WARN: OnName only works with naming routes, not groups.
func ( *Hooks) ( ...OnNameHandler) {
	.app.mutex.Lock()
	.onName = append(.onName, ...)
	.app.mutex.Unlock()
}

// OnGroup is a hook to execute user functions on each group registeration.
// Also you can get group properties by group parameter.
func ( *Hooks) ( ...OnGroupHandler) {
	.app.mutex.Lock()
	.onGroup = append(.onGroup, ...)
	.app.mutex.Unlock()
}

// OnGroupName is a hook to execute user functions on each group naming.
// Also you can get group properties by group parameter.
//
// WARN: OnGroupName only works with naming groups, not routes.
func ( *Hooks) ( ...OnGroupNameHandler) {
	.app.mutex.Lock()
	.onGroupName = append(.onGroupName, ...)
	.app.mutex.Unlock()
}

// OnListen is a hook to execute user functions on Listen, ListenTLS, Listener.
func ( *Hooks) ( ...OnListenHandler) {
	.app.mutex.Lock()
	.onListen = append(.onListen, ...)
	.app.mutex.Unlock()
}

// OnShutdown is a hook to execute user functions after Shutdown.
func ( *Hooks) ( ...OnShutdownHandler) {
	.app.mutex.Lock()
	.onShutdown = append(.onShutdown, ...)
	.app.mutex.Unlock()
}

// OnFork is a hook to execute user function after fork process.
func ( *Hooks) ( ...OnForkHandler) {
	.app.mutex.Lock()
	.onFork = append(.onFork, ...)
	.app.mutex.Unlock()
}

// OnMount is a hook to execute user function after mounting process.
// The mount event is fired when sub-app is mounted on a parent app. The parent app is passed as a parameter.
// It works for app and group mounting.
func ( *Hooks) ( ...OnMountHandler) {
	.app.mutex.Lock()
	.onMount = append(.onMount, ...)
	.app.mutex.Unlock()
}

func ( *Hooks) ( Route) error {
	// Check mounting
	if .app.mountFields.mountPath != "" {
		.path = .app.mountFields.mountPath + .path
		.Path = .path
	}

	for ,  := range .onRoute {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}

func ( *Hooks) ( Route) error {
	// Check mounting
	if .app.mountFields.mountPath != "" {
		.path = .app.mountFields.mountPath + .path
		.Path = .path
	}

	for ,  := range .onName {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}

func ( *Hooks) ( Group) error {
	// Check mounting
	if .app.mountFields.mountPath != "" {
		.Prefix = .app.mountFields.mountPath + .Prefix
	}

	for ,  := range .onGroup {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}

func ( *Hooks) ( Group) error {
	// Check mounting
	if .app.mountFields.mountPath != "" {
		.Prefix = .app.mountFields.mountPath + .Prefix
	}

	for ,  := range .onGroupName {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}

func ( *Hooks) ( ListenData) error {
	for ,  := range .onListen {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}

func ( *Hooks) () {
	for ,  := range .onShutdown {
		if  := ();  != nil {
			log.Errorf("failed to call shutdown hook: %v", )
		}
	}
}

func ( *Hooks) ( int) {
	for ,  := range .onFork {
		if  := ();  != nil {
			log.Errorf("failed to call fork hook: %v", )
		}
	}
}

func ( *Hooks) ( *App) error {
	for ,  := range .onMount {
		if  := ();  != nil {
			return 
		}
	}

	return nil
}