// Package folders are all the routines and sql for managing folders.
package folders

import (
	"errors"
	"strings"

	"git.lyda.ie/kevin/bulletin/storage"
	"git.lyda.ie/kevin/bulletin/this"
)

// ValidFolder validates the folder name for this user.
func ValidFolder(folder string) (storage.Folder, error) {
	if strings.Contains(folder, "%") {
		return storage.Folder{}, errors.New("Folder name cannot contain a %")
	}
	correct := FindFolder(folder)
	if correct.Name == "" {
		return storage.Folder{}, errors.New("Unable to select the folder")
	}
	if !IsFolderAccess(correct.Name, this.User.Login) {
		// TODO: Should be:
		//       WRITE(6,'('' You are not allowed to access folder.'')')
		//       WRITE(6,'('' See '',A,'' if you wish to access folder.'')')
		return storage.Folder{}, errors.New("Unable to select the folder")
	}
	return correct, nil
}

// Values for FolderVisibility.
const (
	FolderPublic      int64 = 0
	FolderSemiPrivate       = 1
	FolderPrivate           = 2
)

// CreateFolder creates a new folder.
func CreateFolder(owner string, options storage.CreateFolderParams) error {
	if !IsAlphaNum(options.Name) {
		return errors.New("Folder can only have letters and numbers")
	}
	options.Name = strings.ToUpper(options.Name)

	ctx := storage.Context()
	tx, err := this.Store.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	qtx := this.Q.WithTx(tx)
	err = qtx.CreateFolder(ctx, options)
	if err != nil {
		return err
	}
	err = qtx.AddFolderOwner(ctx, storage.AddFolderOwnerParams{
		Folder: options.Name,
		Login:  owner,
	})
	if err != nil {
		return err
	}

	// TODO: process this error a bit more to give a better error message.
	return tx.Commit()
}

// ListFolder provides a list of folders that this.User has access to.
func ListFolder() ([]storage.ListFolderRow, error) {
	// TODO: need to check access.
	ctx := storage.Context()
	rows, err := this.Q.ListFolder(ctx)
	if err != nil {
		// TODO: process this error a bit more to give a better error message.
		return []storage.ListFolderRow{}, err
	}
	return rows, nil
}

// FindFolder finds a folder based on the prefix.
func FindFolder(name string) storage.Folder {
	ctx := storage.Context()
	folder, _ := this.Q.FindFolderExact(ctx, name)
	if folder.Name != "" {
		return folder
	}
	folder, _ = this.Q.FindFolderPrefix(ctx, name)
	return folder
}

// IsFolderAccess checks if a user can access a folder.
func IsFolderAccess(name, login string) bool {
	ctx := storage.Context()
	found, _ := this.Q.IsFolderAccess(ctx, storage.IsFolderAccessParams{
		Name:  name,
		Login: login,
	})
	return found == 1
}

// IsFolderOwner checks if a user is a folder owner.
func IsFolderOwner(folder, login string) bool {
	ctx := storage.Context()
	found, _ := this.Q.IsFolderOwner(ctx, storage.IsFolderOwnerParams{
		Folder: folder,
		Login:  login,
	})
	return found == 1
}

// DeleteFolder deletes a folder.
func DeleteFolder(name string) error {
	// TODO: make sure user can delete this table.
	ctx := storage.Context()
	err := this.Q.DeleteFolder(ctx, name)
	// TODO: process this error a bit more to give a better error message.
	if err != nil {
		return err
	}
	return nil
}