package example_test

import (
	"context"
	"log"
	"sync"
	"sync/atomic"
	"time"

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

// ExapmleApp реализует интерфейс IApplication, который отдает серверу параметры подключения,
// секретный ключ шифрования токена авторизации,
// а так же обрабатывает поступающие запросы
type ExampleApp struct {
	addr      string
	secret    []byte
	users     *sync.Map
	groups    *sync.Map
	idCounter int64
}

func (s *ExampleApp) GenerateID() int64 {
	id := atomic.AddInt64(&s.idCounter, 1)
	return id
}

func (s *ExampleApp) Addr() string {
	return s.addr
}

func (s *ExampleApp) Secret() []byte {
	return s.secret
}

func (s *ExampleApp) Executer(r rest.IRequestIn) (rest.IExecuter, bool) {
	switch r.RCommand() {
	case "/user/register":
		return &ExampleRequestRegister{}, true
	case "/user/info":
		return &ExampleRequestUserInfo{}, true
	case "/user/set_avatar":
		return &ExampleRequestSetAvatar{}, true
	default:
		return nil, false
	}
}

var App *ExampleApp

// ExampleNew показывает пример создания и запуска сервера с RestAPI
func ExampleNew() {
	// создаем новый сервер с использованием приложения ExampleApp
	App = &ExampleApp{
		addr:      "localhost:8080",
		secret:    []byte("top-secret"),
		users:     new(sync.Map),
		groups:    new(sync.Map),
		idCounter: 0,
	}
	// Добавляем публичную группу
	groupID := App.GenerateID()
	App.groups.Store(
		groupID,
		&ExampleGroup{
			ID:   groupID,
			Name: "public",
		},
	)
	// создаем сервер
	server := rest.NewServer("localhost:8080", []byte("top-secret"))
	restServ := rest_http.New(App, App, nil)
	restServ.Prepare(server, "/")
	// пробуем запустить его. Если через секунду запуск не удался, будет возвращена ошибка
	if err := server.Listen(time.Second, context.Background()); err != nil {
		// ошибка запуска
		log.Fatal(err)
	}
}