module Turbo::Streams::Broadcasts

def broadcast_action_later_to(*streamables, action:, target: nil, targets: nil, attributes: {}, **rendering)

def broadcast_action_later_to(*streamables, action:, target: nil, targets: nil, attributes: {}, **rendering)
  streamables.flatten!
  streamables.compact_blank!
  if streamables.present?
    target = convert_to_turbo_stream_dom_id(target)
    targets = convert_to_turbo_stream_dom_id(targets, include_selector: true)
    Turbo::Streams::ActionBroadcastJob.perform_later \
      stream_name_from(streamables), action: action, target: target, targets: targets, attributes: attributes, **rendering
  end
end

def broadcast_action_to(*streamables, action:, target: nil, targets: nil, attributes: {}, **rendering)

def broadcast_action_to(*streamables, action:, target: nil, targets: nil, attributes: {}, **rendering)
  broadcast_stream_to(*streamables, content: turbo_stream_action_tag(
    action, target: target, targets: targets, template: render_broadcast_action(rendering), **attributes)
  )
end

def broadcast_after_later_to(*streamables, **opts)

def broadcast_after_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :after, **opts)
end

def broadcast_after_to(*streamables, **opts)

def broadcast_after_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :after, **opts)
end

def broadcast_append_later_to(*streamables, **opts)

def broadcast_append_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :append, **opts)
end

def broadcast_append_to(*streamables, **opts)

def broadcast_append_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :append, **opts)
end

def broadcast_before_later_to(*streamables, **opts)

def broadcast_before_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :before, **opts)
end

def broadcast_before_to(*streamables, **opts)

def broadcast_before_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :before, **opts)
end

def broadcast_prepend_later_to(*streamables, **opts)

def broadcast_prepend_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :prepend, **opts)
end

def broadcast_prepend_to(*streamables, **opts)

def broadcast_prepend_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :prepend, **opts)
end

def broadcast_refresh_later_to(*streamables, request_id: Turbo.current_request_id, **opts)

def broadcast_refresh_later_to(*streamables, request_id: Turbo.current_request_id, **opts)
  stream_name = stream_name_from(streamables)
  refresh_debouncer_for(*streamables, request_id: request_id).debounce do
    Turbo::Streams::BroadcastStreamJob.perform_later stream_name, content: turbo_stream_refresh_tag(request_id: request_id, **opts).to_str # Sidekiq requires job arguments to be valid JSON types, such as String
  end
end

def broadcast_refresh_to(*streamables, **opts)

def broadcast_refresh_to(*streamables, **opts)
  broadcast_stream_to(*streamables, content: turbo_stream_refresh_tag)
end

def broadcast_remove_to(*streamables, **opts)

def broadcast_remove_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :remove, render: false, **opts)
end

def broadcast_render_later_to(*streamables, **rendering)

def broadcast_render_later_to(*streamables, **rendering)
  Turbo::Streams::BroadcastJob.perform_later stream_name_from(streamables), **rendering
end

def broadcast_render_to(*streamables, **rendering)

def broadcast_render_to(*streamables, **rendering)
  broadcast_stream_to(*streamables, content: render_format(:turbo_stream, **rendering))
end

def broadcast_replace_later_to(*streamables, **opts)

def broadcast_replace_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :replace, **opts)
end

def broadcast_replace_to(*streamables, **opts)

def broadcast_replace_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :replace, **opts)
end

def broadcast_stream_to(*streamables, content:)

def broadcast_stream_to(*streamables, content:)
  streamables.flatten!
  streamables.compact_blank!
  if streamables.present?
    ActionCable.server.broadcast stream_name_from(streamables), content
  end
end

def broadcast_update_later_to(*streamables, **opts)

def broadcast_update_later_to(*streamables, **opts)
  broadcast_action_later_to(*streamables, action: :update, **opts)
end

def broadcast_update_to(*streamables, **opts)

def broadcast_update_to(*streamables, **opts)
  broadcast_action_to(*streamables, action: :update, **opts)
end

def refresh_debouncer_for(*streamables, request_id: nil) # :nodoc:

:nodoc:
def refresh_debouncer_for(*streamables, request_id: nil) # :nodoc:
  Turbo::ThreadDebouncer.for("turbo-refresh-debouncer-#{stream_name_from(streamables.including(request_id))}")
end

def render_broadcast_action(rendering)

def render_broadcast_action(rendering)
  content = rendering.delete(:content)
  html    = rendering.delete(:html)
  render  = rendering.delete(:render)
  if render == false
    nil
  else
    content || html || (render_format(:html, **rendering) if rendering.present?)
  end
end

def render_format(format, **rendering)

def render_format(format, **rendering)
  ApplicationController.render(formats: [ format ], **rendering)
end