package pttodo

import (
	"fmt"
	"time"
)

type Todo struct {
	Todo     string
	Details  string   `yaml:",omitempty"`
	Schedule Schedule `yaml:",omitempty"`
	Tags     string   `yaml:",omitempty"`
	Subtasks []Todo   `yaml:",omitempty"`
	TS       TS       `yaml:",omitempty"`
	writeTS  bool
}

func (todo Todo) Triggered() bool {
	last := todo.TS
	next, err := todo.Schedule.Next(last.time())
	return err == nil && time.Now().After(next)
}

func (todo Todo) MarshalYAML() (interface{}, error) {
	if !todo.writeTS {
		todo.TS = 0
	} else {
		todo.TS = TS(todo.TS.time().Unix())
	}
	if fmt.Sprint(todo) == fmt.Sprint(Todo{Todo: todo.Todo}) {
		return todo.Todo, nil
	}
	type Alt Todo
	return (Alt)(todo), nil
}

func (todo *Todo) UnmarshalYAML(unmarshal func(interface{}) error) error {
	*todo = Todo{}
	if err := unmarshal(&todo.Todo); err == nil {
		return nil
	}
	type Alt Todo
	alt := (*Alt)(todo)
	return unmarshal(alt)
}

func (todo Todo) Equals(other Todo) bool {
	if !equalTodoSlices(todo.Subtasks, other.Subtasks) {
		return false
	}
	if todo.TS != other.TS {
		return false
	}
	if todo.Tags != other.Tags {
		return false
	}
	if todo.Schedule != other.Schedule {
		return false
	}
	if todo.Details != other.Details {
		return false
	}
	if todo.Todo != other.Todo {
		return false
	}
	return true
}

func equalTodoSlices(a, b []Todo) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if !a[i].Equals(b[i]) {
			return false
		}
	}
	return true
}
