package db

import (
	"fmt"
	"sort"
	"sync"
	"time"

	"go.skia.org/infra/go/util"

	"github.com/satori/go.uuid"
	"go.skia.org/infra/go/sklog"
)

type inMemoryTaskDB struct {
	tasks    map[string]*Task
	tasksMtx sync.RWMutex
	ModifiedTasks
}

// See docs for TaskDB interface. Does not take any locks.
func (db *inMemoryTaskDB) AssignId(t *Task) error {
	if t.Id != "" {
		return fmt.Errorf("Task Id already assigned: %v", t.Id)
	}
	t.Id = uuid.NewV5(uuid.NewV1(), uuid.NewV4().String()).String()
	return nil
}

// See docs for TaskDB interface.
func (db *inMemoryTaskDB) GetTaskById(id string) (*Task, error) {
	db.tasksMtx.RLock()
	defer db.tasksMtx.RUnlock()
	if task := db.tasks[id]; task != nil {
		return task.Copy(), nil
	}
	return nil, nil
}

// See docs for TaskDB interface.
func (db *inMemoryTaskDB) GetTasksFromDateRange(start, end time.Time) ([]*Task, error) {
	db.tasksMtx.RLock()
	defer db.tasksMtx.RUnlock()

	rv := []*Task{}
	// TODO(borenet): Binary search.
	for _, b := range db.tasks {
		if (b.Created.Equal(start) || b.Created.After(start)) && b.Created.Before(end) {
			rv = append(rv, b.Copy())
		}
	}
	sort.Sort(TaskSlice(rv))
	return rv, nil
}

// See docs for TaskDB interface.
func (db *inMemoryTaskDB) PutTask(task *Task) error {
	return db.PutTasks([]*Task{task})
}

// See docs for TaskDB interface.
func (db *inMemoryTaskDB) PutTasks(tasks []*Task) error {
	db.tasksMtx.Lock()
	defer db.tasksMtx.Unlock()

	// Validate.
	for _, task := range tasks {
		if util.TimeIsZero(task.Created) {
			return fmt.Errorf("Created not set. Task %s created time is %s. %v", task.Id, task.Created, task)
		}

		if existing := db.tasks[task.Id]; existing != nil {
			if !existing.DbModified.Equal(task.DbModified) {
				sklog.Warningf("Cached Task has been modified in the DB. Current:\n%v\nCached:\n%v", existing, task)
				return ErrConcurrentUpdate
			}
		}
	}

	// Insert.
	for _, task := range tasks {
		if task.Id == "" {
			if err := db.AssignId(task); err != nil {
				// Should never happen.
				return err
			}
		}

		task.DbModified = time.Now()

		// TODO(borenet): Keep tasks in a sorted slice.
		db.tasks[task.Id] = task.Copy()
		db.TrackModifiedTask(task)
	}
	return nil
}

// NewInMemoryTaskDB returns an extremely simple, inefficient, in-memory TaskDB
// implementation.
func NewInMemoryTaskDB() TaskDB {
	db := &inMemoryTaskDB{
		tasks: map[string]*Task{},
	}
	return db
}

type inMemoryJobDB struct {
	jobs    map[string]*Job
	jobsMtx sync.RWMutex
	ModifiedJobs
}

func (db *inMemoryJobDB) assignId(j *Job) error {
	if j.Id != "" {
		return fmt.Errorf("Job Id already assigned: %v", j.Id)
	}
	j.Id = uuid.NewV5(uuid.NewV1(), uuid.NewV4().String()).String()
	return nil
}

// See docs for JobDB interface.
func (db *inMemoryJobDB) GetJobById(id string) (*Job, error) {
	db.jobsMtx.RLock()
	defer db.jobsMtx.RUnlock()
	if job := db.jobs[id]; job != nil {
		return job.Copy(), nil
	}
	return nil, nil
}

// See docs for JobDB interface.
func (db *inMemoryJobDB) GetJobsFromDateRange(start, end time.Time) ([]*Job, error) {
	db.jobsMtx.RLock()
	defer db.jobsMtx.RUnlock()

	rv := []*Job{}
	// TODO(borenet): Binary search.
	for _, b := range db.jobs {
		if (b.Created.Equal(start) || b.Created.After(start)) && b.Created.Before(end) {
			rv = append(rv, b.Copy())
		}
	}
	sort.Sort(JobSlice(rv))
	return rv, nil
}

// See docs for JobDB interface.
func (db *inMemoryJobDB) PutJob(job *Job) error {
	return db.PutJobs([]*Job{job})
}

// See docs for JobDB interface.
func (db *inMemoryJobDB) PutJobs(jobs []*Job) error {
	db.jobsMtx.Lock()
	defer db.jobsMtx.Unlock()

	// Validate.
	for _, job := range jobs {
		if util.TimeIsZero(job.Created) {
			return fmt.Errorf("Created not set. Job %s created time is %s. %v", job.Id, job.Created, job)
		}

		if existing := db.jobs[job.Id]; existing != nil {
			if !existing.DbModified.Equal(job.DbModified) {
				sklog.Warningf("Cached Job has been modified in the DB. Current:\n%v\nCached:\n%v", existing, job)
				return ErrConcurrentUpdate
			}
		}
	}

	// Insert.
	for _, job := range jobs {
		if job.Id == "" {
			if err := db.assignId(job); err != nil {
				// Should never happen.
				return err
			}
		}
		job.DbModified = time.Now()

		// TODO(borenet): Keep jobs in a sorted slice.
		db.jobs[job.Id] = job.Copy()
		db.TrackModifiedJob(job)
	}
	return nil
}

// NewInMemoryJobDB returns an extremely simple, inefficient, in-memory JobDB
// implementation.
func NewInMemoryJobDB() JobDB {
	db := &inMemoryJobDB{
		jobs: map[string]*Job{},
	}
	return db
}

// NewInMemoryDB returns an extremely simple, inefficient, in-memory DB
// implementation.
func NewInMemoryDB() DB {
	return NewDB(NewInMemoryTaskDB(), NewInMemoryJobDB(), &CommentBox{})
}
