/*
 * Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*jshint esversion: 6 */

/**
 * A loopback peer connection with one or more streams.
 */
class PeerConnection {
  /**
   * Creates a loopback peer connection. One stream per supplied resolution is
   * created.
   * @param {!Element} videoElement the video element to render the feed on.
   * @param {!Array<!{x: number, y: number}>} resolutions. A width of -1 will
   *     result in disabled video for that stream.
   * @param {?boolean=} cpuOveruseDetection Whether to enable
   *     googCpuOveruseDetection (lower video quality if CPU usage is high).
   *     Default is null which means that the constraint is not set at all.
   */
  constructor(videoElement, resolutions, cpuOveruseDetection=null) {
    this.localConnection = null;
    this.remoteConnection = null;
    this.remoteView = videoElement;
    this.streams = [];
    // Ensure sorted in descending order to conveniently request the highest
    // resolution first through GUM later.
    this.resolutions = resolutions.slice().sort((x, y) => y.w - x.w);
    this.activeStreamIndex = resolutions.length - 1;
    this.badResolutionsSeen = 0;
    if (cpuOveruseDetection !== null) {
      this.pcConstraints = {
        'optional': [{'googCpuOveruseDetection': cpuOveruseDetection}]
      };
    }
    this.rtcConfig = {'sdpSemantics': 'plan-b'};
  }

  /**
   * Starts the connections. Triggers GetUserMedia and starts
   * to render the video on {@code this.videoElement}.
   * @return {!Promise} a Promise that resolves when everything is initalized.
   */
  start() {
    // getUserMedia fails if we first request a low resolution and
    // later a higher one. Hence, sort resolutions above and
    // start with the highest resolution here.
    const promises = this.resolutions.map((resolution) => {
      const constraints = createMediaConstraints(resolution);
      return navigator.mediaDevices
        .getUserMedia(constraints)
        .then((stream) => this.streams.push(stream));
    });
    return Promise.all(promises).then(() => {
      // Start with the smallest video to not overload the machine instantly.
      return this.onGetUserMediaSuccess_(this.streams[this.activeStreamIndex]);
    })
  };

  /**
   * Verifies that the state of the streams are good. The state is good if all
   * streams are active and their video elements report the resolution the
   * stream is in. Video elements are allowed to report bad resolutions
   * numSequentialBadResolutionsForFailure times before failure is reported
   * since video elements occasionally report bad resolutions during the tests
   * when we manipulate the streams frequently.
   * @param {number=} numSequentialBadResolutionsForFailure number of bad
   *     resolution observations in a row before failure is reported.
   * @param {number=} allowedDelta allowed difference between expected and
   *     actual resolution. We have seen videos assigned a resolution one pixel
   *     off from the requested.
   * @throws {Error} in case the state is not-good.
   */
  verifyState(numSequentialBadResolutionsForFailure=10, allowedDelta=1) {
    this.verifyAllStreamsActive_();
    const expectedResolution = this.resolutions[this.activeStreamIndex];
    if (expectedResolution.w < 0 || expectedResolution.h < 0) {
      // Video is disabled.
      return;
    }
    if (!isWithin(
            this.remoteView.videoWidth, expectedResolution.w, allowedDelta) ||
        !isWithin(
            this.remoteView.videoHeight, expectedResolution.h, allowedDelta)) {
      this.badResolutionsSeen++;
    } else if (
        this.badResolutionsSeen < numSequentialBadResolutionsForFailure) {
      // Reset the count, but only if we have not yet reached the limit. If the
      // limit is reached, let keep the error state.
      this.badResolutionsSeen = 0;
    }
    if (this.badResolutionsSeen >= numSequentialBadResolutionsForFailure) {
      throw new Error(
          'Expected video resolution ' +
          resStr(expectedResolution.w, expectedResolution.h) +
          ' but got another resolution ' + this.badResolutionsSeen +
          ' consecutive times. Last resolution was: ' +
          resStr(this.remoteView.videoWidth, this.remoteView.videoHeight));
    }
  }

  verifyAllStreamsActive_() {
    if (this.streams.some((x) => !x.active)) {
      throw new Error('At least one media stream is not active')
    }
  }

  /**
   * Switches to a random stream, i.e., use a random resolution of the
   * resolutions provided to the constructor.
   * @return {!Promise} A promise that resolved when everything is initialized.
   */
  switchToRandomStream() {
    const localStreams = this.localConnection.getLocalStreams();
    const track = localStreams[0];
    if (track != null) {
      this.localConnection.removeStream(track);
      const newStreamIndex = Math.floor(Math.random() * this.streams.length);
      return this.addStream_(this.streams[newStreamIndex])
          .then(() => this.activeStreamIndex = newStreamIndex);
    } else {
      return Promise.resolve();
    }
  }

  onGetUserMediaSuccess_(stream) {
    this.localConnection = new RTCPeerConnection(this.rtcConfig,
      this.pcConstraints);
    this.localConnection.onicecandidate = (event) => {
      this.onIceCandidate_(this.remoteConnection, event);
    };
    this.remoteConnection = new RTCPeerConnection(this.rtcConfig,
      this.pcConstraints);
    this.remoteConnection.onicecandidate = (event) => {
      this.onIceCandidate_(this.localConnection, event);
    };
    this.remoteConnection.onaddstream = (e) => {
      this.remoteView.srcObject = e.stream;
    };
    return this.addStream_(stream);
  }

  addStream_(stream) {
    this.localConnection.addStream(stream);
    return this.localConnection
        .createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1})
        .then((desc) => this.onCreateOfferSuccess_(desc), logError);
  }

  onCreateOfferSuccess_(desc) {
    this.localConnection.setLocalDescription(desc);
    this.remoteConnection.setRemoteDescription(desc);
    return this.remoteConnection.createAnswer().then(
        (desc) => this.onCreateAnswerSuccess_(desc), logError);
  };

  onCreateAnswerSuccess_(desc) {
    this.remoteConnection.setLocalDescription(desc);
    this.localConnection.setRemoteDescription(desc);
  };

  onIceCandidate_(connection, event) {
    if (event.candidate) {
      connection.addIceCandidate(new RTCIceCandidate(event.candidate));
    }
  };
}

/**
 * Checks if a value is within an expected value plus/minus a delta.
 * @param {number} actual
 * @param {number} expected
 * @param {number} delta
 * @return {boolean}
 */
function isWithin(actual, expected, delta) {
  return actual <= expected + delta && actual >= actual - delta;
}

/**
 * Creates constraints for use with GetUserMedia.
 * @param {!{x: number, y: number}} widthAndHeight Video resolution.
 */
function createMediaConstraints(widthAndHeight) {
  let constraint;
  if (widthAndHeight.w < 0) {
    constraint = false;
  } else {
    constraint = {
      width: {exact: widthAndHeight.w},
      height: {exact: widthAndHeight.h}
    };
  }
  return {
    audio: true,
    video: constraint
  };
}

function resStr(width, height) {
  return `${width}x${height}`
}

function logError(err) {
  console.error(err);
}
