import Subscription from “./subscription” import SubscriptionGuarantor from “./subscription_guarantor” import logger from “./logger”

// Collection class for creating (and internally managing) channel subscriptions. // The only method intended to be triggered by the user is ActionCable.Subscriptions#create, // and it should be called through the consumer like so: // // App = {} // App.cable = ActionCable.createConsumer(“ws://example.com/accounts/1”) // App.appearance = App.cable.subscriptions.create(“AppearanceChannel”) // // For more details on how you’d configure an actual channel subscription, see ActionCable.Subscription.

export default class Subscriptions {

constructor(consumer) {
  this.consumer = consumer
  this.guarantor = new SubscriptionGuarantor(this)
  this.subscriptions = []
}

create(channelName, mixin) {
  const channel = channelName
  const params = typeof channel === "object" ? channel : {channel}
  const subscription = new Subscription(this.consumer, params, mixin)
  return this.add(subscription)
}

// Private

add(subscription) {
  this.subscriptions.push(subscription)
  this.consumer.ensureActiveConnection()
  this.notify(subscription, "initialized")
  this.subscribe(subscription)
  return subscription
}

remove(subscription) {
  this.forget(subscription)
  if (!this.findAll(subscription.identifier).length) {
    this.sendCommand(subscription, "unsubscribe")
  }
  return subscription
}

reject(identifier) {
  return this.findAll(identifier).map((subscription) => {
    this.forget(subscription)
    this.notify(subscription, "rejected")
    return subscription
  })
}

forget(subscription) {
  this.guarantor.forget(subscription)
  this.subscriptions = (this.subscriptions.filter((s) => s !== subscription))
  return subscription
}

findAll(identifier) {
  return this.subscriptions.filter((s) => s.identifier === identifier)
}

reload() {
  return this.subscriptions.map((subscription) =>
    this.subscribe(subscription))
}

notifyAll(callbackName, ...args) {
  return this.subscriptions.map((subscription) =>
    this.notify(subscription, callbackName, ...args))
}

notify(subscription, callbackName, ...args) {
  let subscriptions
  if (typeof subscription === "string") {
    subscriptions = this.findAll(subscription)
  } else {
    subscriptions = [subscription]
  }

  return subscriptions.map((subscription) =>
    (typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined))
}

subscribe(subscription) {
  if (this.sendCommand(subscription, "subscribe")) {
    this.guarantor.guarantee(subscription)
  }
}

confirmSubscription(identifier) {
  logger.log(`Subscription confirmed ${identifier}`)
  this.findAll(identifier).map((subscription) =>
    this.guarantor.forget(subscription))
}

sendCommand(subscription, command) {
  const {identifier} = subscription
  return this.consumer.send({command, identifier})
}

}