package application

import (
	"context"
	"time"

	"git.ali33.ru/fcg-xvii/rest"
	"git.ali33.ru/fcg-xvii/rest/rest_http"
	"git.ali33.ru/fcg-xvii/rest/rest_websocket"
)

func New(appConf *AppConfig, swaggerConf *SwaggerConf, ctx context.Context) rest.IApplication {
	app := &Application{
		conf: appConf,
		//Sockets: NewSockets(),
	}
	if swaggerConf != nil && swaggerConf.Enabled {
		app.swagger = NewSwagger(swaggerConf)
		go app.swagger.Start(ctx)
	}
	go app.start(ctx)
	return app
}

type Application struct {
	*Sockets
	conf    *AppConfig
	swagger *Swagger
	//core      any
	ctx       context.Context
	cancel    context.CancelFunc
	chConnect chan rest.IStream
}

func (s *Application) start(ctx context.Context) (err error) {
	s.ctx, s.cancel = context.WithCancel(ctx)
	var server rest.IServer
	if s.conf.SSL {
		server = rest.NewServerTLS(s.conf.Addr, s.conf.Secret, s.conf.TLSKeyPath, s.conf.TLSCertPath)
	} else {
		server = rest.NewServer(s.conf.Addr, s.conf.Secret)
	}
	if s.conf.Http {
		restServ := rest_http.New(s, s.conf.Core, s.conf.GetHTTPHeaders()())
		restServ.Prepare(server, s.conf.GetHttpPrefix())
		//log.Println("http part prepared...")
	}
	if s.conf.Websocket {
		s.chConnect = make(chan rest.IStream)
		ws := rest_websocket.New(s, s.conf.Core)
		ws.Prepare(server, s.conf.GetWebsocketPrefix())
		go s.work()
		//log.Println("websocket engine prepared...")
	}
	if err = server.Listen(time.Second, s.ctx); err != nil {
		s.cancel()
	}
	return
}

func (s *Application) Stop() {
	s.cancel()
}

func (s *Application) Executer(r rest.IRequestIn) (rest.IExecuter, bool) {
	method := s.conf.GetCommandsMethod()
	if command, check := method(r.RCommand()); check {
		return command, true
	}
	return nil, false
}