// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"

#ifdef DEBUG
#define LOG_DEBUG(...) NSLog(__VA_ARGS__);
#else
#define LOG_DEBUG(...) ;
#endif

#define LOG_INFO(...) NSLog(__VA_ARGS__);
#define LOG_FATAL(...)                                                         \
  @throw                                                                       \
      [NSException exceptionWithName:NSInternalInconsistencyException          \
                              reason:[NSString stringWithFormat:__VA_ARGS__]   \
                            userInfo:NULL];

// mem_ensure ensures that m has at least size bytes free.
// If m is NULL, it is created.
static void mem_ensure(GoSeq *m, uint32_t size) {
  size_t cap = m->cap;

  if (cap > m->off + size) {
    return;
  }

  if (cap == 0) {
	  cap = 64;
  }
  while (cap < m->off + size) {
	  cap *= 2;
  }

  m->buf = (uint8_t *)realloc((void *)m->buf, cap);
  if (m->buf == NULL) {
    LOG_FATAL(@"mem_ensure realloc failed, off=%zu, size=%u", m->off, size);
  }
  m->cap = cap;
}

static uint32_t align(uint32_t offset, uint32_t alignment) {
  uint32_t pad = offset % alignment;
  if (pad > 0) {
    pad = alignment - pad;
  }
  return pad + offset;
}

static uint8_t *mem_read(GoSeq *m, uint32_t size, uint32_t alignment) {
  if (size == 0) {
    return NULL;
  }
  if (m == NULL) {
    LOG_FATAL(@"mem_read on NULL GoSeq");
  }
  uint32_t offset = align(m->off, alignment);

  if (m->len - offset < size) {
    LOG_FATAL(@"short read");
  }
  uint8_t *res = m->buf + offset;
  m->off = offset + size;
  return res;
}

static uint8_t *mem_write(GoSeq *m, uint32_t size, uint32_t alignment) {
  if (m->off != m->len) {
    LOG_FATAL(@"write can only append to seq, size: (off=%zu len=%zu, size=%u)",
              m->off, m->len, size);
  }
  uint32_t offset = align(m->off, alignment);
  mem_ensure(m, offset - m->off + size);
  uint8_t *res = m->buf + offset;
  m->off = offset + size;
  m->len = offset + size;
  return res;
}

// extern
void go_seq_free(GoSeq *m) {
  if (m != NULL) {
    free(m->buf);
  }
}

#define MEM_READ(seq, ty) ((ty *)mem_read(seq, sizeof(ty), sizeof(ty)))
#define MEM_WRITE(seq, ty) (*(ty *)mem_write(seq, sizeof(ty), sizeof(ty)))

int go_seq_readInt(GoSeq *seq) {
  int64_t v = go_seq_readInt64(seq);
  return v; // Assume that Go-side used WriteInt to encode 'int' value.
}

void go_seq_writeInt(GoSeq *seq, int v) { go_seq_writeInt64(seq, v); }

BOOL go_seq_readBool(GoSeq *seq) {
  int8_t v = go_seq_readInt8(seq);
  return v ? YES : NO;
}

void go_seq_writeBool(GoSeq *seq, BOOL v) { go_seq_writeInt8(seq, v ? 1 : 0); }

int8_t go_seq_readInt8(GoSeq *seq) {
  int8_t *v = MEM_READ(seq, int8_t);
  return v == NULL ? 0 : *v;
}
void go_seq_writeInt8(GoSeq *seq, int8_t v) { MEM_WRITE(seq, int8_t) = v; }

int16_t go_seq_readInt16(GoSeq *seq) {
  int16_t *v = MEM_READ(seq, int16_t);
  return v == NULL ? 0 : *v;
}
void go_seq_writeInt16(GoSeq *seq, int16_t v) { MEM_WRITE(seq, int16_t) = v; }

int32_t go_seq_readInt32(GoSeq *seq) {
  int32_t *v = MEM_READ(seq, int32_t);
  return v == NULL ? 0 : *v;
}
void go_seq_writeInt32(GoSeq *seq, int32_t v) { MEM_WRITE(seq, int32_t) = v; }

int64_t go_seq_readInt64(GoSeq *seq) {
  int64_t *v = MEM_READ(seq, int64_t);
  return v == NULL ? 0 : *v;
}
void go_seq_writeInt64(GoSeq *seq, int64_t v) { MEM_WRITE(seq, int64_t) = v; }

float go_seq_readFloat32(GoSeq *seq) {
  float *v = MEM_READ(seq, float);
  return v == NULL ? 0 : *v;
}
void go_seq_writeFloat32(GoSeq *seq, float v) { MEM_WRITE(seq, float) = v; }

double go_seq_readFloat64(GoSeq *seq) {
  double *v = MEM_READ(seq, double);
  return v == NULL ? 0 : *v;
}
void go_seq_writeFloat64(GoSeq *seq, double v) { MEM_WRITE(seq, double) = v; }

NSString *go_seq_readUTF8(GoSeq *seq) {
  int32_t len = *MEM_READ(seq, int32_t);
  if (len == 0) {
    return NULL;
  }
  const void *buf = (const void *)mem_read(seq, len, 1);
  return [[NSString alloc] initWithBytes:buf
                                  length:len
                                encoding:NSUTF8StringEncoding];
}

void go_seq_writeUTF8(GoSeq *seq, NSString *s) {
  int32_t len = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
  MEM_WRITE(seq, int32_t) = len;

  if (len == 0 && s.length > 0) {
    LOG_INFO(@"unable to incode an NSString into UTF-8");
    return;
  }

  char *buf = (char *)mem_write(seq, len, 1);
  NSUInteger used;
  [s getBytes:buf
           maxLength:len
          usedLength:&used
            encoding:NSUTF8StringEncoding
             options:0
               range:NSMakeRange(0, [s length])
      remainingRange:NULL];
  if (used < len) {
    buf[used] = '\0';
  }
  return;
}

NSData *go_seq_readByteArray(GoSeq *seq) {
  int64_t sz = *MEM_READ(seq, int64_t);
  if (sz == 0) {
    return [NSData data];
  }
  // BUG(hyangah): it is possible that *ptr is already GC'd by Go runtime.
  void *ptr = (void *)(*MEM_READ(seq, int64_t));
  return [NSData dataWithBytes:ptr length:sz];
}

void go_seq_writeByteArray(GoSeq *seq, NSData *data) {
  int64_t sz = data.length;
  MEM_WRITE(seq, int64_t) = sz;
  if (sz == 0) {
    return;
  }

  int64_t ptr = (int64_t)data.bytes;
  MEM_WRITE(seq, int64_t) = ptr;
  return;
}

void go_seq_send(char *descriptor, int code, GoSeq *req, GoSeq *res) {
  if (descriptor == NULL) {
    LOG_FATAL(@"invalid NULL descriptor");
  }
  uint8_t *req_buf = NULL;
  size_t req_len = 0;
  if (req != NULL) {
    req_buf = req->buf;
    req_len = req->len;
  }

  uint8_t **res_buf = NULL;
  size_t *res_len = NULL;
  if (res == NULL) {
    mem_ensure(res, 64);
  }
  res_buf = &res->buf;
  res_len = &res->len;

  GoString desc;
  desc.p = descriptor;
  desc.n = strlen(descriptor);
  Send(desc, (GoInt)code, req_buf, req_len, res_buf, res_len);
}

#define IS_FROM_GO(refnum) ((refnum) < 0)

// init_seq is called when the Go side is initialized.
void init_seq() {
  // TODO(hyangah): initialize a map of Objective-C objects passed to Go.
}

GoSeqRef *go_seq_readRef(GoSeq *seq) {
  int32_t refnum = go_seq_readInt32(seq);
  if (!IS_FROM_GO(refnum)) {
    LOG_FATAL(@"passing Objective-C objects is not implemented yet");
    return NULL;
  }
  return [[GoSeqRef alloc] initWithRefnum:refnum obj:NULL];
}

void go_seq_writeRef(GoSeq *seq, GoSeqRef *v) {
  int32_t refnum = v.refnum;
  if (!IS_FROM_GO(refnum)) {
    LOG_FATAL(@"passing Objective-C objects is not implemented yet");
    return;
  }
  go_seq_writeInt32(seq, refnum);
}

@implementation GoSeqRef {
}
- (id)init {
  LOG_FATAL(@"GoSeqRef init is disallowed");
  return nil;
}

- (id)initWithRefnum:(int32_t)refnum obj:(id)obj {
  if (!IS_FROM_GO(refnum)) {
    LOG_FATAL(@"GoSeqRef init with non-Go object reference (refnum: %d)",
              refnum);
    return nil;
  }
  self = [super init];
  if (self) {
    _refnum = refnum;
    _obj = obj;
  }
  return self;
}

- (void)dealloc {
  if (IS_FROM_GO(_refnum)) {
    DestroyRef(_refnum);
  }
}
@end
