//
// Copyright 2019 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#import "Channel/Sources/EDOSocketChannel.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <sys/un.h>

#import "Channel/Sources/EDOChannel.h"
#import "Channel/Sources/EDOChannelUtil.h"
#import "Channel/Sources/EDOSocket.h"

#pragma mark - Socket Connection Extension

@interface EDOSocketChannel ()
// The dispatch io channel to send and receive I/O data from the underlying socket.
@property(readonly, nonatomic) dispatch_io_t channel;
// The dispatch queue where the receive handler block will be dispatched to.
@property(readonly, nonatomic) dispatch_queue_t handlerQueue;
@end

#pragma mark - Socket Connection

@implementation EDOSocketChannel
@dynamic valid;

+ (instancetype)channelWithSocket:(EDOSocket *)socket {
  return [self channelWithSocket:socket handlerQueue:nil];
}

+ (instancetype)channelWithSocket:(EDOSocket *)socket handlerQueue:(dispatch_queue_t)handlerQueue {
  return [[self alloc] initWithDispatchIO:[socket releaseAsDispatchIO] handlerQueue:handlerQueue];
}

- (instancetype)initWithDispatchIO:(dispatch_io_t)channel {
  return [self initWithDispatchIO:channel handlerQueue:nil];
}

- (instancetype)initWithDispatchIO:(dispatch_io_t)channel
                      handlerQueue:(dispatch_queue_t)handlerQueue {
  NSParameterAssert(channel != nil);

  self = [self initWithHandlerQueue:handlerQueue];
  if (self) {
    _channel = channel;
  }
  return self;
}

- (instancetype)initWithHandlerQueue:(dispatch_queue_t)handlerQueue {
  self = [super init];
  if (self) {
    // For internal IO and event handlers, it is equivalent to creating it as a serial queue as they
    // are not reentrant and only one block will be scheduled by dispatch io and dispatch source.
    if (handlerQueue) {
      _handlerQueue = handlerQueue;
    } else {
      // Use QOS_CLASS_USER_INITIATED as the default because eDO communication is often in the
      // critical path of user-driven test execution, and using a lower QoS can lead to priority
      // inversion issues.
      dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(
          DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0);
      _handlerQueue = dispatch_queue_create("com.google.edo.socketChannel.handler", attributes);
    }
  }
  return self;
}

- (void)dealloc {
  [self invalidate];
}

#pragma mark - EDOChannel

- (void)sendData:(NSData *)data withCompletionHandler:(EDOChannelSentHandler)handler {
  dispatch_queue_t handlerQueue = self.handlerQueue;
  if (!self.channel) {
    dispatch_async(handlerQueue, ^{
      if (handler) {
        handler(self, [NSError errorWithDomain:NSPOSIXErrorDomain code:0 userInfo:nil]);
      }
    });
    return;
  }

  dispatch_data_t totalData = EDOBuildFrameFromDataWithQueue(data, handlerQueue);
  dispatch_io_write(
      self.channel, 0, totalData, handlerQueue, ^(bool done, dispatch_data_t _, int errCode) {
        if (!done) {
          return;
        }

        if (handler) {
          dispatch_async(handlerQueue, ^{
            NSError *error;
            if (errCode != 0) {
              error = [NSError errorWithDomain:NSPOSIXErrorDomain code:errCode userInfo:nil];
            }
            handler(self, error);
          });
        }
      });
}

- (void)receiveDataWithHandler:(EDOChannelReceiveHandler)handler {
  [self receiveDataWithQueue:self.handlerQueue handler:handler];
}

- (void)receiveDataWithQueue:(dispatch_queue_t)queue
                     handler:(EDOChannelReceiveHandler _Nullable)handler {
  dispatch_queue_t handlerQueue = queue;
  dispatch_io_t channel = self.channel;
  if (!channel) {
    dispatch_async(handlerQueue, ^{
      // TODO(haowoo): Add better error code define.
      handler(self, nil,
              [NSError errorWithDomain:NSInternalInconsistencyException code:0 userInfo:nil]);
    });
    return;
  }

  // Accessing __block variable has to be atomic in order to prevent from data racing. Here because
  // ARC inserts release at the end of scope such that reads and writes can happen in different
  // threads/queues, using handlerQueue as an isolation queue to ensure its atomicity. For detail,
  // see b/171321939.
  dispatch_async(handlerQueue, ^{
    __block dispatch_data_t dataReceived;
    __block size_t remainingDataSize;
    dispatch_io_handler_t dataHandler = ^(bool done, dispatch_data_t data, int error) {
      if (error || !data) {
        if (handler) {
          dispatch_async(handlerQueue, ^{
            handler(self, nil,
                    [NSError errorWithDomain:NSPOSIXErrorDomain code:error userInfo:nil]);
          });
        }
        return;
      }
      remainingDataSize -= dispatch_data_get_size(data);
      dataReceived = dataReceived ? dispatch_data_create_concat(dataReceived, data) : data;

      if (remainingDataSize > 0) {
        return;
      }

      NSMutableData *receivedData =
          [NSMutableData dataWithCapacity:dispatch_data_get_size(dataReceived)];
      dispatch_data_apply(dataReceived, ^bool(dispatch_data_t region, size_t offset,
                                              const void *buffer, size_t size) {
        [receivedData appendBytes:buffer length:size];
        return YES;
      });

      if (handler) {
        dispatch_async(handlerQueue, ^{
          handler(self, receivedData, nil);
        });
      }
    };

    dispatch_io_handler_t frameHandler = ^(bool done, dispatch_data_t data, int error) {
      size_t payloadSize = EDOGetPayloadSizeFromFrameData(data);
      if (payloadSize > 0) {
        remainingDataSize = payloadSize;
        if (![self readDispatchIOWithDataSize:remainingDataSize handler:dataHandler] && handler) {
          handler(self, nil, nil);
        }
      } else {
        // Close the channel on errors and closed sockets.
        if (error != 0 || payloadSize == 0) {
          [self invalidate];
        }

        // Execute the block on closing the channel.
        if (payloadSize == 0 && error == 0 && handler) {
          dispatch_async(handlerQueue, ^{
            handler(self, nil, nil);
          });
        }
      }
    };

    [self readDispatchIOWithDataSize:EDOGetPayloadHeaderSize() handler:frameHandler];
  });
}

/** @see -[EDOChannel isValid] */
- (BOOL)isValid {
  @synchronized(self) {
    return _channel != NULL;
  }
}

/** @see -[EDOChannel invalidate] */
- (void)invalidate {
  @synchronized(self) {
    if (_channel) {
      dispatch_io_close(_channel, 0);
      _channel = NULL;
    }
  }
}

#pragma mark - Private

/**
 * Atomically checks the validity of the socket channel and calls dispatch_io_read if it's valid.
 *
 * @param dataSize The number of bytes to be read through dispatch_io_read.
 * @param handler  The handler to process the data read by dispatch_io_read.
 *
 * @return @c YES if dispatch_io_read is called; @c NO otherwise.
 */
- (BOOL)readDispatchIOWithDataSize:(size_t)dataSize handler:(dispatch_io_handler_t)handler {
  @synchronized(self) {
    if (_channel) {
      dispatch_io_read(_channel, 0, dataSize, _handlerQueue, handler);
    }
    return _channel != NULL;
  }
}

@end
