#!/usr/bin/env ruby

require 'json'
require 'time'

DAYS  = 60 * 60 * 24
WEEKS = DAYS * 7

TASKWARRIOR_DATE_FORMAT = "%Y%m%dT060000Z"

# Find the -final- task state that's passed to us.
json_task = $stdin.map{ |line| line }.last

task = JSON.parse(json_task)
last_task_form = json_task

# Only modify tasks that are done, but have a recur.
# Emit all other tasks' final states unchanged.
unless task.has_key?('status') && task.has_key?('every') && (task['status'] == 'completed')
  puts(json_task)
  exit 0
end

#
# We have an every-recurring task -- modify it!
#

unless task.has_key? 'due'
  puts "ERROR: task #{task['id']} has an 'every' recurrance, but no due date!"
  exit -1
end

# Figure our our next recurrance based on the taskwarrior period/duration syntax.
previous_due_date  = Time.parse(task['due'])
recur_date = case task['every']
  when /P(\d+)D/ then previous_due_date + ($1.to_i * DAYS)
  when /P(\d+)W/ then previous_due_date + ($1.to_i * WEEKS)
  when /P(\d+)M/ then Time.new(previous_due_date.year, previous_due_date.month + $1.to_i, previous_due_date.day)
  when /P(\d+)H/ then Time.new(previous_due_date.year + $1.to_i, previous_due_date.month, previous_due_date.day)
  else
      puts "ERROR: task #{task['id']} has unsupported'every' duration #{task['every']}"
      exit -1
end

# Mutate the task to be pending, still, but with new dates.
task['status'] = 'pending'
task['due']    = recur_date.strftime(TASKWARRIOR_DATE_FORMAT)


# If this task has ancillary dates, maintain the offset between them and the due date.
['wait', 'start'].each do |field|
  if task.has_key?(field)
    field_offset   = previous_due_date - Time.parse(task[field])
    new_field_date = Time.parse(task['due']) - field_offset

    task[field] = new_field_date.strftime(TASKWARRIOR_DATE_FORMAT)
  end
end

# Emit the task back to TaskWarrior.
puts task.to_json
