//
//  tank
//
//  Import and Playlist Daemon for autoradio project
//
//
//  Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at>
//
//  This file is part of tank.
//
//  tank is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  any later version.
//
//  tank is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with tank. If not, see <http://www.gnu.org/licenses/>.
//

package store

import (
	//	"encoding/binary"
	"errors"
	//"strconv"
	"time"
)

const (
	// well-known table names
	migrationsTn = "__migrations__"
)

var (
	ErrNotImplented = errors.New("not implemented")
	ErrNotFound     = errors.New("not found")
	ErrFileInUse    = errors.New("file is in use by at least one playlist")
)

//******* Groups

type Group struct {
	Name      string    `json:"name" gorm:"primary_key"`
	CreatedAt time.Time `json:"created"`
	UpdatedAt time.Time `json:"updated"`
}

func (g Group) String() string {
	return g.Name
}

//******* Files

// type ImportState int

// const (
// 	ImportNew ImportState = iota
// 	ImportPending
// 	ImportRunning
// 	ImportDone
// 	ImportAborted
// )

// func (s ImportState) String() string {
// 	switch s {
// 	case ImportNew:
// 		return "new"
// 	case ImportPending:
// 		return "pending"
// 	case ImportRunning:
// 		return "running"
// 	case ImportDone:
// 		return "done"
// 	case ImportAborted:
// 		return "aborted"
// 	}
// 	return "unknown"
// }

// func (s *ImportState) fromString(str string) error {
// 	switch str {
// 	case "new":
// 		*s = ImportNew
// 	case "pending":
// 		*s = ImportPending
// 	case "running":
// 		*s = ImportRunning
// 	case "done":
// 		*s = ImportDone
// 	case "aborted":
// 		*s = ImportAborted
// 	default:
// 		return errors.New("invalid import state: '" + str + "'")
// 	}
// 	return nil
// }

// func (s ImportState) MarshalText() (data []byte, err error) {
// 	data = []byte(s.String())
// 	return
// }

// func (s *ImportState) UnmarshalText(data []byte) (err error) {
// 	return s.fromString(string(data))
// }

// type ImportLogLine struct {
// 	Timestamp time.Time `json:"timestamp"`
// 	Message   string    `json:"message"`
// }

// type ImportLog []ImportLogLine

// func (l ImportLog) Append(message string) {
// 	l = append(l, ImportLogLine{time.Now(), message})
// }

type Import struct {
	//	State   ImportState `json:"state"`
	Success bool `json:"success"`
	//	Log     ImportLog   `json:"log"`
}

type FileSource struct {
	FileName string `json:"filename"`
	Hash     string `json:"hash"`
	Import   Import `json:"import" gorm:"embedded;embedded_prefix:import__"`
}

type FileMetadata struct {
	// TODO: actually a full-text index would be nice here...
	Artist string `json:"artist" gorm:"index"`
	Title  string `json:"title" gorm:"index"`
	Album  string `json:"album" gorm:"index"`
	// TODO: add more fields
}

type File struct {
	ID        uint         `json:"id" gorm:"primary_key"`
	CreatedAt time.Time    `json:"created"`
	UpdatedAt time.Time    `json:"updated"`
	GroupName string       `json:"group" gorm:"not null;index"`
	Group     Group        `json:"-"`
	Source    FileSource   `json:"source" gorm:"embedded;embedded_prefix:source__"`
	Metadata  FileMetadata `json:"metadata" gorm:"embedded;embedded_prefix:metadata__"`
	Size      uint64       `json:"size"`
}

type Files map[uint64]File

//******* Playlists

type PlaylistEntry struct {
	ID         uint   `json:"id" gorm:"primary_key"`
	PlaylistID uint   `json:"-" gorm:"not null;index;unique_index:unique_playlist_line_numbers"`
	LineNum    uint   `json:"line-num" gorm:"not null;unique_index:unique_playlist_line_numbers"`
	Uri        string `json:"uri"`
	File       File   `json:"file"`
	FileID     uint   `json:"-" gorm:"index"`
}

type Playlist struct {
	ID              uint      `json:"id" gorm:"primary_key"`
	CreatedAt       time.Time `json:"created"`
	UpdatedAt       time.Time `json:"updated"`
	GroupName       string    `json:"group" gorm:"not null;index"`
	Group           Group     `json:"-"`
	PlaylistEntries []PlaylistEntry
}

type Playlists map[uint64]Playlist

//****************