package logic

import (
	"database/sql"
	"errors"
	"sevenkeys/database"
)

var ErrCouldNotGetStorageAreaId error = errors.New("Could not get storage area ID.")

func GetStorageAreaId(db *sql.DB, storageAreaName string) (int, error) {
	id, err := database.GetStorageAreaIdByName(db, storageAreaName)
	if err == nil {
		return id, nil
	}

	if err == database.ErrStorageAreaDoesNotExist {
		storageOptions, err := GetStorageAreaSearchOptions(db)
		if err != nil {
			return id, err
		}

		id, _, err := GenericSearch(storageOptions)
		if err == nil {
			return id, nil
		}

		return id, ErrCouldNotGetStorageAreaId
	}

	return id, ErrCouldNotGetStorageAreaId
}

func CreateStorageArea(db *sql.DB, storageArea database.StorageArea) error {
	// TODO: Check if there's already a storage are with the same name
	// TODO: Check if the type entered is valid
	err := database.InsertStorageArea(db, storageArea)
	if err != nil {
		return err
	}

	return nil
}

type StorageAreaSearchOptions map[string]int

func GetStorageAreaSearchOptions(db *sql.DB) (StorageAreaSearchOptions, error) {
	var options StorageAreaSearchOptions = make(map[string]int)

	storageAreas, err := database.GetAllStorageAreas(db)
	if err != nil {
		return options, err
	}

	for _, area := range storageAreas {
		options[area.Name] = area.Id
	}

	return options, nil
}

func storeAfterLastCard(db *sql.DB, cardLocation database.CardLocation) (int64, error) {
	lastPosition, err := database.GetLastPositionInStorageArea(db, cardLocation.StorageAreaId)
	if err != nil {
		return -1, err
	}

	cardLocation.Position = lastPosition + 1

	id, err := database.InsertCardLocation(db, cardLocation)
	if err != nil {
		return -1, err
	}

	return id, nil
}

func storeInEmptySlot(db *sql.DB, cardLocation database.CardLocation, cardLocationId int) error {
	cardLocation.Id = cardLocationId
	err := database.InsertCardInExistingLocation(db, cardLocation)
	if err != nil {
		return err
	}

	return nil
}

func StoreCard(db *sql.DB, cardLocation database.CardLocation) (int64, error) {
	storageAreaType, err := database.GetStorageAreaTypeById(db, cardLocation.StorageAreaId)
	if err != nil {
		return -1, err
	}

	if storageAreaType == database.StorageAreaTypeBinder {
		nextEmptySlotId, err := database.GetNextEmptySlotInBinder(db, cardLocation.StorageAreaId)

		if err == database.ErrNoEmptySlotsInBinder {
			id, err := storeAfterLastCard(db, cardLocation)
			if err != nil {
				return -1, err
			}

			return id, nil
		} else if err != nil {
			return -1, err
		} else {
			err = storeInEmptySlot(db, cardLocation, nextEmptySlotId)
			if err != nil {
				return -1, err
			}
		}

		return int64(nextEmptySlotId), nil
	}

	id, err := storeAfterLastCard(db, cardLocation)
	if err != nil {
		return -1, err
	}

	return id, nil
}

func Replace(db *sql.DB, cardLocationId int, cardPrintingId string) error {
	cardLocation := database.CardLocation{
		Id:             cardLocationId,
		CardPrintingId: cardPrintingId,
	}

	return database.InsertCardInExistingLocation(db, cardLocation)
}