#include "nsIThread.idl"
#include "nsIDOMWindow.idl"
#include "nsIPropertyBag2.idl"

interface nsIDOMMediaStream;
interface nsIDOMDataChannel;

/*
 * Manager interface to PeerConnection.js so it is accessible from C++.
 */
[scriptable, uuid(c2218bd2-2648-4701-8fa6-305d3379e9f8)]
interface IPeerConnectionManager : nsISupports
{
  boolean hasActivePeerConnection(in unsigned long innerWindowID);
};

%{C++
#define IPEERCONNECTION_MANAGER_CONTRACTID "@mozilla.org/dom/peerconnectionmanager;1"
%}

/* Do not confuse with nsIDOMRTCPeerConnection. This interface is purely for
 * communication between the PeerConnection JS DOM binding and the C++
 * implementation in SIPCC.
 *
 * See media/webrtc/signaling/include/PeerConnectionImpl.h
 */
[scriptable, uuid(cf9152f0-c9a8-4093-9435-1daa056e0177)]
interface IPeerConnectionObserver : nsISupports
{
  /* Constants */
  const long kReadyState = 0x1;
  const long kIceState = 0x2;
  const long kSdpState = 0x3;
  const long kSipccState = 0x4;
  const long kSignalingState = 0x5;

  /* JSEP callbacks */
  void onCreateOfferSuccess(in string offer);
  void onCreateOfferError(in unsigned long name, in string message);
  void onCreateAnswerSuccess(in string answer);
  void onCreateAnswerError(in unsigned long name, in string message);
  void onSetLocalDescriptionSuccess();
  void onSetRemoteDescriptionSuccess();
  void onSetLocalDescriptionError(in unsigned long name, in string message);
  void onSetRemoteDescriptionError(in unsigned long name, in string message);
  void onAddIceCandidateSuccess();
  void onAddIceCandidateError(in unsigned long name, in string message);

  /* Data channel callbacks */
  void notifyDataChannel(in nsIDOMDataChannel channel);
  void notifyConnection();
  void notifyClosedConnection();

  /* Notification of one of several types of state changed */
  void onStateChange(in unsigned long state);

  /* Changes to MediaStreams */
  void onAddStream(in nsIDOMMediaStream stream);
  void onRemoveStream();
  void onAddTrack();
  void onRemoveTrack();

  /* When SDP is parsed and a candidate line is found this method is called.
   * It should hook back into the media transport to notify it of ICE candidates
   * listed in the SDP PeerConnectionImpl does not parse ICE candidates, just
   * pulls them out of the SDP.
   */
  void foundIceCandidate(in string candidate);
};

[scriptable, uuid(930dce8b-7c5e-4393-b8c0-cb3a928f68bd)]
interface IPeerConnection : nsISupports
{
  const unsigned long kHintAudio = 0x00000001;
  const unsigned long kHintVideo = 0x00000002;

  const long kActionNone = -1;
  const long kActionOffer = 0;
  const long kActionAnswer = 1;
  const long kActionPRAnswer = 2;

  const long kIceGathering = 0;
  const long kIceWaiting = 1;
  const long kIceChecking = 2;
  const long kIceConnected = 3;
  const long kIceFailed = 4;

  /* for readyState on Peer Connection */
  const long kNew = 0;
  const long kNegotiating = 1;
  const long kActive = 2;
  const long kClosing = 3;
  const long kClosed = 4;

  /* RTCSignalingState from WebRTC spec */
  const long kSignalingInvalid            = 0;
  const long kSignalingStable             = 1;
  const long kSignalingHaveLocalOffer     = 2;
  const long kSignalingHaveRemoteOffer    = 3;
  const long kSignalingHaveLocalPranswer  = 4;
  const long kSignalingHaveRemotePranswer = 5;
  const long kSignalingClosed             = 6;

  /* for 'type' in DataChannelInit dictionary */
  const unsigned short kDataChannelReliable = 0;
  const unsigned short kDataChannelPartialReliableRexmit = 1;
  const unsigned short kDataChannelPartialReliableTimed = 2;

  /* Constants for 'name' in error callbacks */
  const unsigned long kNoError                          = 0; // Test driver only
  const unsigned long kInvalidConstraintsType           = 1;
  const unsigned long kInvalidCandidateType             = 2;
  const unsigned long kInvalidMediastreamTrack          = 3;
  const unsigned long kInvalidState                     = 4;
  const unsigned long kInvalidSessionDescription        = 5;
  const unsigned long kIncompatibleSessionDescription   = 6;
  const unsigned long kIncompatibleConstraints          = 7;
  const unsigned long kIncompatibleMediaStreamTrack     = 8;
  const unsigned long kInternalError                    = 9;
  const unsigned long kMaxErrorType                     = 9; // Same as final error

  /* Must be called first. Observer events will be dispatched on the thread provided */
  [implicit_jscontext] void initialize(in IPeerConnectionObserver observer, in nsIDOMWindow window,
                  [optional] in jsval iceServers,
                  [optional] in nsIThread thread);

  /* JSEP calls */
  [implicit_jscontext] void createOffer(in jsval constraints);
  [implicit_jscontext] void createAnswer(in jsval constraints);
  void setLocalDescription(in long action, in string sdp);
  void setRemoteDescription(in long action, in string sdp);

  /* Adds the stream created by GetUserMedia */
  void addStream(in nsIDOMMediaStream stream);
  void removeStream(in nsIDOMMediaStream stream);
  void closeStreams();

  [implicit_jscontext] readonly attribute jsval localStreams; // MediaStream[]
  [implicit_jscontext] readonly attribute jsval remoteStreams; // MediaStream[]

  /* As the ICE candidates roll in this one should be called each time
   * in order to keep the candidate list up-to-date for the next SDP-related
   * call PeerConnectionImpl does not parse ICE candidates, just sticks them
   * into the SDP.
   */
  void addIceCandidate(in string candidate, in string mid, in unsigned short level);

  /* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
  void close();

  /* Attributes */
  readonly attribute string localDescription;
  readonly attribute string remoteDescription;

  readonly attribute unsigned long iceState;
  readonly attribute unsigned long readyState;
  readonly attribute unsigned long signalingState;
  readonly attribute unsigned long sipccState;

  /* Data channels */
  nsIDOMDataChannel createDataChannel(in ACString label, in ACString protocol,
    in unsigned short type, in boolean outOfOrderAllowed,
    in unsigned short maxTime, in unsigned short maxNum,
    in boolean externalNegotiated, in unsigned short stream);
  void connectDataConnection(in unsigned short localport,
    in unsigned short remoteport, in unsigned short numstreams);
};
