/*
 *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#import "RTCMediaStream+Private.h"

#import "RTCAudioTrack+Private.h"
#import "RTCMediaStreamTrack+Private.h"
#import "RTCPeerConnectionFactory+Private.h"
#import "RTCVideoTrack+Private.h"
#import "helpers/NSString+StdString.h"

@implementation RTC_OBJC_TYPE (RTCMediaStream) {
  RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory;
  rtc::Thread *_signalingThread;
  NSMutableArray *_audioTracks /* accessed on _signalingThread */;
  NSMutableArray *_videoTracks /* accessed on _signalingThread */;
  rtc::scoped_refptr<webrtc::MediaStreamInterface> _nativeMediaStream;
}

- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
                       streamId:(NSString *)streamId {
  NSParameterAssert(factory);
  NSParameterAssert(streamId.length);
  std::string nativeId = [NSString stdStringForString:streamId];
  rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
      factory.nativeFactory->CreateLocalMediaStream(nativeId);
  return [self initWithFactory:factory nativeMediaStream:stream];
}

- (NSArray<RTC_OBJC_TYPE(RTCAudioTrack) *> *)audioTracks {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall([self]() { return self.audioTracks; });
  }
  return [_audioTracks copy];
}

- (NSArray<RTC_OBJC_TYPE(RTCVideoTrack) *> *)videoTracks {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall([self]() { return self.videoTracks; });
  }
  return [_videoTracks copy];
}

- (NSString *)streamId {
  return [NSString stringForStdString:_nativeMediaStream->id()];
}

- (void)addAudioTrack:(RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrack {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall(
        [audioTrack, self]() { return [self addAudioTrack:audioTrack]; });
  }
  if (_nativeMediaStream->AddTrack(audioTrack.nativeAudioTrack)) {
    [_audioTracks addObject:audioTrack];
  }
}

- (void)addVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)videoTrack {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall(
        [videoTrack, self]() { return [self addVideoTrack:videoTrack]; });
  }
  if (_nativeMediaStream->AddTrack(videoTrack.nativeVideoTrack)) {
    [_videoTracks addObject:videoTrack];
  }
}

- (void)removeAudioTrack:(RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrack {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall(
        [audioTrack, self]() { return [self removeAudioTrack:audioTrack]; });
  }
  NSUInteger index = [_audioTracks indexOfObjectIdenticalTo:audioTrack];
  if (index == NSNotFound) {
    RTC_LOG(LS_INFO) << "|removeAudioTrack| called on unexpected RTC_OBJC_TYPE(RTCAudioTrack)";
    return;
  }
  if (_nativeMediaStream->RemoveTrack(audioTrack.nativeAudioTrack)) {
    [_audioTracks removeObjectAtIndex:index];
  }
}

- (void)removeVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)videoTrack {
  if (!_signalingThread->IsCurrent()) {
    return _signalingThread->BlockingCall(
        [videoTrack, self]() { return [self removeVideoTrack:videoTrack]; });
  }
  NSUInteger index = [_videoTracks indexOfObjectIdenticalTo:videoTrack];
  if (index == NSNotFound) {
    RTC_LOG(LS_INFO) << "|removeVideoTrack| called on unexpected RTC_OBJC_TYPE(RTCVideoTrack)";
    return;
  }

  if (_nativeMediaStream->RemoveTrack(videoTrack.nativeVideoTrack)) {
    [_videoTracks removeObjectAtIndex:index];
  }
}

- (NSString *)description {
  return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCMediaStream):\n%@\nA=%lu\nV=%lu",
                                    self.streamId,
                                    (unsigned long)self.audioTracks.count,
                                    (unsigned long)self.videoTracks.count];
}

#pragma mark - Private

- (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream {
  return _nativeMediaStream;
}

- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
              nativeMediaStream:
                  (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream {
  NSParameterAssert(nativeMediaStream);
  if (self = [super init]) {
    _factory = factory;
    _signalingThread = factory.signalingThread;

    webrtc::AudioTrackVector audioTracks = nativeMediaStream->GetAudioTracks();
    webrtc::VideoTrackVector videoTracks = nativeMediaStream->GetVideoTracks();

    _audioTracks = [NSMutableArray arrayWithCapacity:audioTracks.size()];
    _videoTracks = [NSMutableArray arrayWithCapacity:videoTracks.size()];
    _nativeMediaStream = nativeMediaStream;

    for (auto &track : audioTracks) {
      RTCMediaStreamTrackType type = RTCMediaStreamTrackTypeAudio;
      RTC_OBJC_TYPE(RTCAudioTrack) *audioTrack =
          [[RTC_OBJC_TYPE(RTCAudioTrack) alloc] initWithFactory:_factory
                                                    nativeTrack:track
                                                           type:type];
      [_audioTracks addObject:audioTrack];
    }

    for (auto &track : videoTracks) {
      RTCMediaStreamTrackType type = RTCMediaStreamTrackTypeVideo;
      RTC_OBJC_TYPE(RTCVideoTrack) *videoTrack =
          [[RTC_OBJC_TYPE(RTCVideoTrack) alloc] initWithFactory:_factory
                                                    nativeTrack:track
                                                           type:type];
      [_videoTracks addObject:videoTrack];
    }
  }
  return self;
}

@end
