package storage

import (
	"galaxy/model/client"
	"galaxy/model/order"
	"galaxy/model/report"
)

type Storage interface {
	UIStorage
	FileExists(string) (bool, string, error)
	ReadFile(string) ([]byte, error)
	WriteFile(string, []byte) error
	DeleteFile(string) error
	ListFiles() ([]string, error)

	StateExists() (bool, error)
	LoadState() (client.State, error)
	SaveState(client.State) error
}

// UIStorage manages Client's data local storing and retrieval.
// It performs all I/O operations asynchronously to avoid UI main thread blocking.
type UIStorage interface {
	// StateExistsAsync check asynchronously for previously saved [model.State] exists on the filesystem.
	// Passed callback func will will accept false and non-nil error in case of I/O or decoding errors occuried,
	// otherwise bool parameter will indicate existence of previously stores state
	StateExistsAsync(func(bool, error))

	// LoadStateAsync loads Client's [model.State] from filesystem data asynchronously.
	// Passed callback func will accept non-nil error in case of I/O or decoding errors occuried,
	// otherwise callback func accepts loaded [model.State].
	LoadStateAsync(func(client.State, error))

	// SaveStateAsync stores Client's state at the filesystem asynchronously.
	// I/O or encoding error may occur, it that case callback func will be called with non-nil error.
	SaveStateAsync(client.State, func(error))

	// ReportExistsAsync asynchronously checks whether given [model.GameID] and turn number exists in the Storage.
	// Passed callback func will will accept non-nil error in case of I/O or decoding errors occuried,
	// otherwise callback func accepts boolean result.
	ReportExistsAsync(client.GameID, uint, func(bool, error))

	// LoadReportAsync loads a [report.Report] for a given [model.GameID] and turn number from filesystem asynchronously.
	// Passed callback func will will accept non-nil error in case of I/O or decoding errors occuried,
	// otherwise callback func accepts loaded [report.Report].
	LoadReportAsync(client.GameID, uint, func(report.Report, error))

	// SaveReportAsync stores given [report.Report] for a given [model.GameID] and turn number at the filesystem asynchronously.
	// I/O or encoding error may occur, it that case callback func will be called with non-nil error.
	SaveReportAsync(client.GameID, uint, report.Report, func(error))

	// LoadOrderAsync loads a [order.Order] for a given [model.GameID] and turn number from filesystem asynchronously.
	// Passed callback func will will accept non-nil error in case of I/O or decoding errors occuried,
	// otherwise callback func accepts loaded [order.Order].
	LoadOrderAsync(client.GameID, uint, func(order.UserGamesOrder, error))

	// SaveOrderAsync stores given [order.Order] for a given [model.GameID] and turn number at the filesystem asynchronously.
	// I/O or encoding error may occur, it that case callback func will be called with non-nil error.
	SaveOrderAsync(client.GameID, uint, order.UserGamesOrder, func(error))
}
