require 'java'

import 'org.bukkit.Bukkit'

module Purugin
  # Set of tasks for scheduling synchronous or asynchronous tasks.  Note, that most of
  # the underlying Bukkit API in which Purugin is based is not actually thread-safe.  Try
  # and use sync_task as much as possible but be aware that if you run a sync task too long
  # people will see the game lag out.
  #
  # In order to use the task methods your including class must have a _server_ and _plugin_
  # method defined.
  module Tasks
    # Will periodically call block passed.  So long as the block continues to return
    # something truthy it will continue to run.
    class AsyncRunnable < Java::org::bukkit::scheduler::BukkitRunnable
      def initialize(&code)
        @code = code
      end

      def run
        @code[] || cancel
      end
    end

    TICKS_PER_SECOND = 20
    
    def sync_task(delay=0, repeat=-1, &block)
      delay, repeat = (delay.to_f * TICKS_PER_SECOND).to_i, (repeat.to_f * TICKS_PER_SECOND).to_i
      code = java.lang.Runnable.impl &block
      
      raise ArgumentError.new "delay must be a positive value" if delay < 0
      
      if repeat > -1
        raise ArgumentError.new "repeat must be positive value" if repeat <= 0
        task_id = Bukkit.server.scheduler.schedule_sync_repeating_task self, code, delay, repeat
      else
        task_id = Bukkit.server.scheduler.schedule_sync_delayed_task self, code, delay
      end
      
      raise Purugin::ScheduleFailedError.new if task_id == -1
      task_id
    end
    
    def async_task(delay=0, repeat=-1, &block)
      delay, repeat = (delay.to_f * TICKS_PER_SECOND).to_i, (repeat.to_f * TICKS_PER_SECOND).to_i
      code = AsyncRunnable.new &block

      raise ArgumentError.new "delay must be a positive value" if delay < 0
      
      if repeat > -1
        raise ArgumentError.new "repeat must be positive value" if repeat <= 0
        task_id = code.runTaskTimer self, delay, repeat # FIXME: this should repeat in Runnable to cancel
      else
        task_id = code.runTaskTimer self, 0, delay
      end
      
      raise Purugin::ScheduleFailedError.new if task_id == -1
      task_id
    end
  end
end
