package database

import (
	"time"

	"github.com/go-pg/pg"
)

type DB interface {
	Close() error
	AddBook(book Book) error
	GetBooks(query string, length int, start int) (books []Book, num int, err error)
	GetNewBooks(query string, length int, start int) (books []Book, num int, err error)
	GetBookID(id string) (Book, error)
	DeleteBook(id string) error
	UpdateBook(id string, data map[string]interface{}) error
	ActiveBook(id string) error
	IsBookActive(id string) bool
	AddUser(name string, pass string) error
	AddRawUser(name string, hpass []byte, salt []byte, role string) error
	GetRole(name string) (string, error)
	SetPassword(name string, pass string) error
	ValidPassword(name string, pass string) bool
	AddNews(text string) error
	AddRawNews(text string, date time.Time) error
	GetNews(num int, days int) (news []New, err error)
	AddStats(stats interface{}) error
	GetVisitedBooks() (books []Book, err error)
	GetDownloadedBooks() (books []Book, err error)
	GetTags() ([]string, error)
}

const (
	tagsDisplay = 50
)

type pgDB struct {
	sql       *pg.DB
	tags      []string
	bookCount int
}

// Options for the database
type Options struct {
	Addr     string
	User     string
	Password string
	Name     string
}

// Init the database connection
func Init(options Options) (DB, error) {
	network := "tcp"
	if options.Addr[0] == '/' {
		network = "unix"
	}
	sql := pg.Connect(&pg.Options{
		Network:  network,
		Addr:     options.Addr,
		User:     options.User,
		Password: options.Password,
		Database: options.Name,
	})
	// TODO: create db

	var db pgDB
	db.sql = sql
	go db.tagUpdater()
	go db.countUpdater()

	return &db, nil
}

// Close the database connection
func (db pgDB) Close() error {
	return db.sql.Close()
}

func RO(db DB) DB {
	return &roDB{db}
}