package todotxt import ( "errors" "sort" "time" ) // Flags for defining sort element and order. const ( SORT_PRIORITY_ASC = iota SORT_PRIORITY_DESC SORT_CREATED_DATE_ASC SORT_CREATED_DATE_DESC SORT_COMPLETED_DATE_ASC SORT_COMPLETED_DATE_DESC SORT_DUE_DATE_ASC SORT_DUE_DATE_DESC ) // Sort allows a TodoList to be sorted by certain predefined fields. // See constants SORT_* for fields and sort order. func (todolist *TodoList) Sort(sortFlag int) error { switch sortFlag { case SORT_PRIORITY_ASC, SORT_PRIORITY_DESC: todolist.sortByPriority(sortFlag) case SORT_CREATED_DATE_ASC, SORT_CREATED_DATE_DESC: todolist.sortByCreatedDate(sortFlag) case SORT_COMPLETED_DATE_ASC, SORT_COMPLETED_DATE_DESC: todolist.sortByCompletedDate(sortFlag) case SORT_DUE_DATE_ASC, SORT_DUE_DATE_DESC: todolist.sortByDueDate(sortFlag) default: return errors.New("unrecognized sort option") } return nil } type todolistSort struct { todolists TodoList by func(t1, t2 *Todo) bool } func (ts *todolistSort) Len() int { return len(ts.todolists) } func (ts *todolistSort) Swap(l, r int) { ts.todolists[l], ts.todolists[r] = ts.todolists[r], ts.todolists[l] } func (ts *todolistSort) Less(l, r int) bool { return ts.by(&ts.todolists[l], &ts.todolists[r]) } func (todolist *TodoList) sortBy(by func(t1, t2 *Todo) bool) *TodoList { ts := &todolistSort{ todolists: *todolist, by: by, } sort.Sort(ts) return todolist } func (todolist *TodoList) sortByPriority(order int) *TodoList { todolist.sortBy(func(t1, t2 *Todo) bool { if order == SORT_PRIORITY_ASC { // ASC if t1.HasPriority() && t2.HasPriority() { return t1.Priority < t2.Priority } return t1.HasPriority() } // DESC if t1.HasPriority() && t2.HasPriority() { return t1.Priority > t2.Priority } return !t1.HasPriority() }) return todolist } func sortByDate(asc bool, hasDate1, hasDate2 bool, date1, date2 time.Time) bool { if asc { // ASC if hasDate1 && hasDate2 { return date1.Before(date2) } return hasDate2 } // DESC if hasDate1 && hasDate2 { return date1.After(date2) } return !hasDate2 } func (todolist *TodoList) sortByCreatedDate(order int) *TodoList { todolist.sortBy(func(t1, t2 *Todo) bool { return sortByDate(order == SORT_CREATED_DATE_ASC, t1.HasCreatedDate(), t2.HasCreatedDate(), t1.CreatedDate, t2.CreatedDate) }) return todolist } func (todolist *TodoList) sortByCompletedDate(order int) *TodoList { todolist.sortBy(func(t1, t2 *Todo) bool { return sortByDate(order == SORT_COMPLETED_DATE_ASC, t1.HasCompletedDate(), t2.HasCompletedDate(), t1.CompletedDate, t2.CompletedDate) }) return todolist } func (todolist *TodoList) sortByDueDate(order int) *TodoList { todolist.sortBy(func(t1, t2 *Todo) bool { return sortByDate(order == SORT_DUE_DATE_ASC, t1.HasDueDate(), t2.HasDueDate(), t1.DueDate, t2.DueDate) }) return todolist }