# frozen_string_literal: true

module Litany
  module Delegator
    def delegate_to(target, *method_names, private: true, singleton: true)
      method_names.each do |method_name|
        if singleton
          define_singleton_method method_name, _delegate(target, method_name)
          singleton_class.__send__ :private, method_name if private
        else
          define_method method_name, _delegate(target, method_name)
          private method_name if private
        end
      end
    end

    def passthrough(*method_names, private: true)
      method_names.each do |method_name|
        define_method(method_name) { |*args, &block| self.class.__send__ method_name, *args, &block }
        private method_name if private
      end
    end

    private

    def _delegate(target, method_name)
      proc do |*args, &block|
        route_to = target.is_a?(Proc) ? instance_exec(&target) : target
        route_to.__send__ method_name, *args, &block
      end
    end
  end
end
