/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * 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. Neither the name of Google Inc. nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 COPYRIGHT
 * OWNER OR CONTRIBUTORS 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.
 */

[
    Conditional=MEDIA_STREAM,
    ActiveDOMObject,
    Constructor(Dictionary rtcIceServers, [Optional] Dictionary mediaConstraints),
    RaisesException,
    CallWith=ScriptExecutionContext,
    EventTarget
] interface RTCPeerConnection {
    [RaisesException] void createOffer([Callback] RTCSessionDescriptionCallback successCallback, [Callback,Optional=DefaultIsUndefined] RTCErrorCallback failureCallback, [Optional] Dictionary mediaConstraints);

    [RaisesException] void createAnswer([Callback] RTCSessionDescriptionCallback successCallback, [Callback, Optional=DefaultIsUndefined] RTCErrorCallback failureCallback, [Optional] Dictionary mediaConstraints);

    [RaisesException] void setLocalDescription(RTCSessionDescription description, [Callback, Optional=DefaultIsUndefined] VoidCallback successCallback, [Callback, Optional=DefaultIsUndefined] RTCErrorCallback failureCallback);
    [GetterRaisesException] readonly attribute RTCSessionDescription localDescription;

    [RaisesException] void setRemoteDescription(RTCSessionDescription description, [Callback, Optional=DefaultIsUndefined] VoidCallback successCallback, [Callback, Optional=DefaultIsUndefined] RTCErrorCallback failureCallback);
    [GetterRaisesException] readonly attribute RTCSessionDescription remoteDescription;

    readonly attribute DOMString signalingState;

    [RaisesException] void updateIce([Optional] Dictionary configuration, [Optional] Dictionary mediaConstraints);

    [RaisesException] void addIceCandidate(RTCIceCandidate candidate);

    readonly attribute DOMString iceGatheringState;
    readonly attribute DOMString iceConnectionState;

    sequence<MediaStream> getLocalStreams();
    sequence<MediaStream> getRemoteStreams();
    MediaStream getStreamById(DOMString streamId);

    [StrictTypeChecking, RaisesException] void addStream(MediaStream stream, [Optional] Dictionary mediaConstraints);
    [StrictTypeChecking, RaisesException] void removeStream(MediaStream stream);

    void getStats([Callback] RTCStatsCallback successCallback, [Optional=DefaultIsUndefined] MediaStreamTrack selector);

    [RaisesException] RTCDataChannel createDataChannel([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString label, [Optional] Dictionary options);

    [RaisesException] RTCDTMFSender createDTMFSender(MediaStreamTrack track);

    [RaisesException] void close();

    attribute EventListener onnegotiationneeded;
    attribute EventListener onicecandidate;
    attribute EventListener onsignalingstatechange;
    attribute EventListener onaddstream;
    attribute EventListener onremovestream;
    attribute EventListener oniceconnectionstatechange;
    attribute EventListener ondatachannel;

    // EventTarget interface
    void addEventListener(DOMString type,
                          EventListener listener,
                          [Optional] boolean useCapture);
    void removeEventListener(DOMString type,
                             EventListener listener,
                             [Optional] boolean useCapture);
    [RaisesException] boolean dispatchEvent(Event event);
};

