#import "WLVAudioDevice.h"

#import <AudioUnit/AudioUnit.h>
#import <WebRTC/WebRTC.h>

@implementation WLVAudioDevice {
    id<RTCAudioDeviceDelegate> _delegate;
    double _sampleRate;
    NSInteger _channels;
    BOOL _isInitialized;
    BOOL _isRecording;
}

#pragma mark - RTCAudioDevice properties

- (double)deviceInputSampleRate {
    return _sampleRate > 0 ? _sampleRate : 48000.0;
}

- (NSTimeInterval)inputIOBufferDuration {
    return 0.01;
}

- (NSInteger)inputNumberOfChannels {
    return _channels > 0 ? _channels : 1;
}

- (NSTimeInterval)inputLatency {
    return 0.0;
}

- (double)deviceOutputSampleRate {
    return 48000.0;
}

- (NSTimeInterval)outputIOBufferDuration {
    return 0.01;
}

- (NSInteger)outputNumberOfChannels {
    return 1;
}

- (NSTimeInterval)outputLatency {
    return 0.0;
}

- (BOOL)isInitialized {
    return _isInitialized;
}

- (BOOL)initializeWithDelegate:(id<RTCAudioDeviceDelegate>)delegate {
    _delegate = delegate;
    _isInitialized = YES;
    return YES;
}

- (BOOL)terminateDevice {
    _delegate = nil;
    _isInitialized = NO;
    _isRecording = NO;
    return YES;
}

- (BOOL)isPlayoutInitialized {
    return YES;
}

- (BOOL)initializePlayout {
    return YES;
}

- (BOOL)isPlaying {
    return NO;
}

- (BOOL)startPlayout {
    return YES;
}

- (BOOL)stopPlayout {
    return YES;
}

- (BOOL)isRecordingInitialized {
    return YES;
}

- (BOOL)initializeRecording {
    return YES;
}

- (BOOL)isRecording {
    return _isRecording;
}

- (BOOL)startRecording {
    _isRecording = YES;
    return YES;
}

- (BOOL)stopRecording {
    _isRecording = NO;
    return YES;
}

#pragma mark - Push API

- (void)pushAudioData:(NSData *)data sampleRate:(double)sampleRate channels:(NSInteger)channels {
    id<RTCAudioDeviceDelegate> delegate = _delegate;
    if (!delegate || data.length == 0 || channels <= 0) {
        return;
    }

    _sampleRate = sampleRate;
    _channels = channels;

    NSUInteger frameCount = data.length / (sizeof(int16_t) * (NSUInteger)channels);
    if (frameCount == 0) {
        return;
    }

    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0].mNumberChannels = (UInt32)channels;
    bufferList.mBuffers[0].mDataByteSize = (UInt32)data.length;
    bufferList.mBuffers[0].mData = (void *)data.bytes;

    AudioUnitRenderActionFlags flags = 0;
    AudioTimeStamp timestamp = {0};
    timestamp.mFlags = kAudioTimeStampSampleTimeValid;

    RTCAudioDeviceDeliverRecordedDataBlock deliverBlock = delegate.deliverRecordedData;
    deliverBlock(&flags, &timestamp, 0, (UInt32)frameCount, &bufferList, nil, nil);
}

@end
