# frozen_string_literal: true

require 'eventmachine'
require 'em-http-request'

require 'tueor/async_command'

module Tueor

  # Extend this mixin into check base classes
  module Mixin
    class << self
      def extended(target)
        target.include InstanceMixin
      end
    end
  end

  # Included by the Mixin module when extended
  module InstanceMixin
    def command(command, shell: false, &block)
      AsyncCommand.new(command, shell: shell, &block)
    end

    def read_file(path, &block)
      # should be portable to windows with the type command, failing that we can look at ruby based read file
      # with EM's Defer helper.
      AsyncCommand.new(:cat).param(path).execute(&block)
    end

    def request(url, method: :get, body: nil, middleware: [], tries: 1, try: 1, &block)
      raise "Unsupported method `#{method}` supplied." unless [:get, :post, :delete].include?(method)

      connection = EventMachine::HttpRequest.new url

      middleware.each do |mw|
        mw = [mw] unless mw.is_a? Array
        connection.use(*mw)
      end

      req = connection.send(method, body: body)

      callback = proc {
        status = req.response_header.status
        if try < tries && (status >= 500 || status < 200)
          request(url, method: method, body: body, middleware: middleware, tries: tries, try: (try + 1), &block)
        else
          yield status, req.response, req.error unless block.nil?
        end
      }

      req.callback(&callback)
      req.errback(&callback)
    end

    def when_true(predicate, timeout: 2, started_at: nil, &block)
      started_at ||= Time.now
      elapsed = Time.now - started_at

      if predicate.call
        yield false, elapsed
      elsif elapsed >= timeout
        yield true, elapsed
      else
        EventMachine.next_tick { when_true(predicate, timeout: timeout, started_at: started_at, &block) }
      end
    end

  end
end