package rest

import (
	"io"

	"git.ali33.ru/fcg-xvii/go-tools/json"
)

type RequestType byte

const (
	RequestTypeMessage RequestType = iota
	RequestTypeEvent
	RequestTypeAnswer
)

type IRequest interface {
	Type() RequestType
	IsAuth() bool
	SetAuth(auth json.Map)
	Command() string
	Auth() json.Map
	Data() json.Map
	FileKeys() []string
	File(name string) (IReadCloserLen, bool)
	GenerateToken(data json.Map, expire int64) (string, error)
	Root() any
	Core() any
	ResponseSuccess(data json.Map, files map[string]IReadCloserLen) IResponse
	ResponseError(code int, err IErrorArgs) IResponse
	Close()
}

type Request struct {
	rType         RequestType
	auth          json.Map
	command       string
	data          json.Map
	files         map[string]IReadCloserLen
	core          any
	root          any
	generateToken func(data json.Map, expire int64) (string, error)
	//Response      func(data json.Map, files map[string]io.ReadCloser) IResponse
}

// сеттеры

func (s *Request) SetType(rType RequestType) {
	s.rType = rType
}

func (s *Request) SetAuth(auth json.Map) {
	s.auth = auth
}

func (s *Request) SetCommand(command string) {
	s.command = command
}

func (s *Request) SetData(data json.Map) {
	s.data = data
}

func (s *Request) SetFiles(files map[string]IReadCloserLen) {
	s.files = files
}

func (s *Request) SetRoot(root any) {
	s.root = root
}

func (s *Request) SetCore(core any) {
	s.core = core
}

func (s *Request) SetGenerateToken(generateToken func(data json.Map, expire int64) (string, error)) {
	s.generateToken = generateToken
}

// методы интерфейса

func (s *Request) Type() RequestType {
	return RequestTypeMessage
}

func (s *Request) IsAuth() bool {
	return s.auth != nil
}

func (s *Request) Command() string {
	return s.command
}

func (s *Request) Auth() json.Map {
	return s.auth
}

func (s *Request) Data() json.Map {
	return s.data
}

func (s *Request) FileKeys() []string {
	keys := make([]string, 0, len(s.files))
	for key := range s.files {
		keys = append(keys, key)
	}
	return keys
}

func (s *Request) File(name string) (io.Reader, bool) {
	file, ok := s.files[name]
	return file, ok
}

func (s *Request) GenerateToken(data json.Map, expire int64) (string, error) {
	return s.generateToken(data, expire)
}

func (s *Request) Root() any {
	return s.root
}

func (s *Request) Core() any {
	return s.core
}

func (s *Request) ResponseSuccess(data json.Map, files map[string]IReadCloserLen) IResponse {
	return &Response{
		code:  200,
		data:  data,
		files: files,
	}
}

func (s *Request) ResponseError(code int, err IErrorArgs) IResponse {
	return &Response{
		code: code,
		err:  err,
	}
}
