/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef TALK_SESSION_PHONE_CALL_H_
#define TALK_SESSION_PHONE_CALL_H_

#include <string>
#include <map>
#include <vector>
#include <deque>
#include "talk/base/messagequeue.h"
#include "talk/p2p/base/session.h"
#include "talk/p2p/client/socketmonitor.h"
#include "talk/xmpp/jid.h"
#include "talk/session/phone/mediasessionclient.h"
#include "talk/session/phone/voicechannel.h"
#include "talk/session/phone/audiomonitor.h"

namespace cricket {

class MediaSessionClient;

class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
 public:
  Call(MediaSessionClient *session_client,
       bool video = false, bool mux = false);
  ~Call();

  Session *InitiateSession(const buzz::Jid &jid);
  void AcceptSession(BaseSession *session);
  void RejectSession(BaseSession *session);
  void TerminateSession(BaseSession *session);
  void Terminate();
  void SetLocalRenderer(VideoRenderer* renderer);
  void SetVideoRenderer(BaseSession *session, uint32 ssrc,
                        VideoRenderer* renderer);
  void AddStream(BaseSession *session, uint32 voice_ssrc, uint32 video_ssrc);
  void RemoveStream(BaseSession *session, uint32 voice_ssrc, uint32 video_ssrc);
  void StartConnectionMonitor(BaseSession *session, int cms);
  void StopConnectionMonitor(BaseSession *session);
  void StartAudioMonitor(BaseSession *session, int cms);
  void StopAudioMonitor(BaseSession *session);
  void Mute(bool mute);
  void PressDTMF(int event);

  const std::vector<Session *> &sessions();
  uint32 id();
  bool video() const { return video_; }
  bool muted() const { return muted_; }

  // Setting this to false will cause the call to have a longer timeout and
  // for the SignalSetupToCallVoicemail to never fire.
  void set_send_to_voicemail(bool send_to_voicemail) {
    send_to_voicemail_ = send_to_voicemail;
  }
  bool send_to_voicemail() { return send_to_voicemail_; }

  // Sets a flag on the chatapp that will redirect the call to voicemail once
  // the call has been terminated
  sigslot::signal0<> SignalSetupToCallVoicemail;
  sigslot::signal2<Call *, Session *> SignalAddSession;
  sigslot::signal2<Call *, Session *> SignalRemoveSession;
  sigslot::signal3<Call *, BaseSession *, BaseSession::State>
      SignalSessionState;
  sigslot::signal3<Call *, BaseSession *, Session::Error>
      SignalSessionError;
  sigslot::signal3<Call *, Session *, const std::string &>
      SignalReceivedTerminateReason;
  sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
      SignalConnectionMonitor;
  sigslot::signal2<Call *, const MediaInfo&> SignalMediaMonitor;
  sigslot::signal2<Call *, const AudioInfo&> SignalAudioMonitor;
  sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
      SignalVideoConnectionMonitor;
  sigslot::signal2<Call *, const MediaInfo&> SignalVideoMediaMonitor;

 private:
  void OnMessage(talk_base::Message *message);
  void OnSessionState(BaseSession *session, BaseSession::State state);
  void OnSessionError(BaseSession *session, Session::Error error);
  void OnReceivedTerminateReason(Session *session, const std::string &reason);
  void IncomingSession(Session *session, const SessionDescription* offer);
  // Returns true on success.
  bool AddSession(Session *session, const SessionDescription* offer);
  void RemoveSession(Session *session);
  void EnableChannels(bool enable);
  void Join(Call *call, bool enable);
  void OnConnectionMonitor(VoiceChannel *channel,
                           const std::vector<ConnectionInfo> &infos);
  void OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info);
  void OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info);
  void OnConnectionMonitor(VideoChannel *channel,
                           const std::vector<ConnectionInfo> &infos);
  void OnMediaMonitor(VideoChannel *channel, const MediaInfo& info);
  VoiceChannel* GetVoiceChannel(BaseSession* session);
  VideoChannel* GetVideoChannel(BaseSession* session);
  void ContinuePlayDTMF();

  uint32 id_;
  MediaSessionClient *session_client_;
  std::vector<Session *> sessions_;
  std::map<std::string, VoiceChannel *> voice_channel_map_;
  std::map<std::string, VideoChannel *> video_channel_map_;
  VideoRenderer* local_renderer_;
  bool video_;
  bool mux_;
  bool muted_;
  bool send_to_voicemail_;

  // DTMF tones have to be queued up so that we don't flood the call.  We
  // keep a deque (doubely ended queue) of them around.  While one is playing we
  // set the playing_dtmf_ bit and schedule a message in XX msec to clear that
  // bit or start the next tone playing.
  std::deque<int> queued_dtmf_;
  bool playing_dtmf_;

  friend class MediaSessionClient;
};

}  // namespace cricket

#endif  // TALK_SESSION_PHONE_CALL_H_
