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)
	IncViews(ID string) error
	IncDownloads(ID string) error
	GetFrontPage() FrontPage
}

const (
	tagsDisplay    = 50
	booksFrontPage = 6
)

type pgDB struct {
	sql       *pg.DB
	frontPage FrontPage
}

type FrontPage struct {
	Count    int
	Last     []Book
	Visited  []Book
	Download []Book
	Tags     []string
}

// 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.frontPageUpdater()

	return &db, nil
}

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

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