/**
 * This file is part of the Meeds project (https://meeds.io/).
 *
 * Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.exoplatform.ws.frameworks.cometd;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import org.cometd.bayeux.server.ServerSession;
import org.cometd.server.ServerChannelImpl;
import org.mortbay.cometd.continuation.EXoContinuationBayeux;

public class ContinuationService {

  private final EXoContinuationBayeux bayeux;

  /**
   * @param bayeux
   */
  public ContinuationService(EXoContinuationBayeux bayeux) {
    this.bayeux = bayeux;
  }

  /**
   * Send individual message to client.
   * 
   * @param eXoId the user ID
   * @param channel the channel you want to send the message. The client must
   *          listen to this channel to receive it
   * @param data the data you want to send to the client
   */
  public void sendMessage(String eXoId, String channel, Object data) {
    sendMessage(eXoId, channel, data, null);
  }

  /**
   * Send individual message to client.
   * 
   * @param eXoId the user ID
   * @param channel the channel you want to send the message. The client must
   *          listen to this channel to receive it
   * @param data the data you want to send to the client
   * @param id the id of message if you set null will be generate automatically
   */
  public void sendMessage(String eXoId, String channel, Object data, String id) {
    bayeux.sendMessage(eXoId, channel, data, id);
  }

  /**
   * @param exoId the id of client (exoId).
   * @return Get client by eXoId.
   */
  public ServerSession getClientByExoId(String exoId) {
    return bayeux.getClientByEXoId(exoId);
  }

  /**
   * @param id the id of client (cometd id)
   * @return Get client by id (id generated by cometd service).
   */
  public ServerSession getClient(String id) {
    return bayeux.getSession(id);
  }

  /**
   * @return all registered client.
   */
  public Collection<ServerSession> getClients() {
    return bayeux.getSessions();
  }

  /**
   * @param channel the channel id.
   * @return Return true if channel exist else false.
   */
  public boolean hasChannel(String channel) {
    return (bayeux.getChannel(channel) != null);
  }

  /**
   * @return timeout of client reconnect.
   */
  public long getTimeout() {
    return bayeux.getTimeout();
  }

  /**
   * Use {@link #isPresent(String)} instead.
   * One user can have multiple session, it doesn't make sense to check if he has subscribed for one channel.
   * This method can only check for channel subscribing status in non-clustering environment.
   * 
   * @param eXoId the client id (as eXoId).
   * @param channel the id of channel.
   * @return true if client subscribe to channel else false.
   */
  @Deprecated 
  public boolean isSubscribe(String eXoId, String channel) {
    ServerChannelImpl channelImpl = (ServerChannelImpl) bayeux.getChannel(channel);
    Collection<ServerSession> collection = channelImpl.getSubscribers();
    for (Iterator<ServerSession> iterator = collection.iterator(); iterator.hasNext();) {
      ServerSession client = (ServerSession) iterator.next();
      if (bayeux.isSubscribed(eXoId, client.getId()))
        return true;
    }
    return false;
  }
  
  public boolean isPresent(String eXoID) {
    return bayeux.isPresent(eXoID);
  }

  /**
   * Send message to all client that listen channel.
   * 
   * @param channel the id of channel that need send message
   * @param data that send
   */
  public void sendBroadcastMessage(String channel, Object data) {
    sendBroadcastMessage(channel, data, null);
  }

  /**
   * Send message to all client that listen channel.
   * 
   * @param channel the id of channel that need send message
   * @param data that send
   * @param msgId id of message
   */
  public void sendBroadcastMessage(String channel, Object data, String msgId) {
    bayeux.sendBroadcastMessage(channel, data, msgId);
  }

  /**
   * @param eXoId the client id (as eXoId).
   * @return Return userToken for the client.
   */
  public String getUserToken(String eXoId) {
    return bayeux.getUserToken(eXoId);
  }
  
  public Set<String> getConnectedUserIds() {
    return bayeux.getConnectedUserIds();
  }
}
