package schedule

import (
	"errors"
	"fmt"
	"sync"
)

var (
	alltask [TaskLevel_MAX][]*STask
	tasklk  sync.Mutex
)

func GetAllTaskStatus() string {
	return fmt.Sprintln(alltask)
}

func RegisteSTask(task RegistedTask) (err error, taskhd TaskHd) {
	tasklk.Lock()
	defer func() {
		tasklk.Unlock()
		if tmperr := recover(); tmperr != nil {
			fmt.Println("Has panic:", tmperr)
			err = errors.New("Panic when registe task!")
		}
	}()

	if task.GetTaskLevel() < TaskLevel_0 || task.GetTaskLevel() >= TaskLevel_MAX {
		return errors.New("TaskLevel error"), nil
	}

	if len(task.GetName()) == 0 {
		return errors.New("Must registe a name!"), nil
	}

	if task.GetTaskLevel == nil || task.GetName == nil ||
		task.IsActive == nil || task.Do == nil ||
		task.Resume == nil || task.Interrupt == nil {
		return errors.New("All interfaces registed can not be nil!"), nil
	}

	for _, leveltask := range alltask {
		for _, atask := range leveltask {
			if atask.Task.GetName() == task.GetName() {
				return errors.New("The task has been registed!"), nil
			}
		}
	}

	var tmp STask
	tmp.Task = task
	tmp.TaskStatus = TaskStatus_Init

	alltask[int(task.GetTaskLevel())] = append(alltask[int(task.GetTaskLevel())], &tmp)

	return nil, &tmp
}

func UnRegisteTask(taskName string) (err error) {
	tasklk.Lock()
	defer func() {
		tasklk.Unlock()
		if tmperr := recover(); tmperr != nil {
			fmt.Println("Has panic:", tmperr)
			err = errors.New("Panic when registe task!")
		}
	}()

	for level, leveltask := range alltask {
		for no, task := range leveltask {
			if task.Task.GetName() == taskName {
				alltask[level] = append(leveltask[:no], leveltask[no+1:]...)
				return nil
			}
		}
	}

	return errors.New("Can not find the task!")
}

func FindSTaskBySCmd(cmd SCMD) *STask {
	for _, leveltask := range alltask {
		for _, stask := range leveltask {
			if arr := stask.Task.GetSupportedSCmd(); len(arr) > 0 {
				for _, supportedcmd := range arr {
					if supportedcmd == cmd {
						return stask
					}
				}
			}
		}
	}

	return nil
}
