exports.createServer = null
exports.connect =
exports.isIP =
exports.isIPv4 =
exports.isIPv6 =
  function () { return true };

const { NSocketClient, ConnData } = require("../../socket.js")

function concatTypedArrays(a, b) { // a, b TypedArray of same type
  let c = new Uint8Array(a.byteLength + b.byteLength);
  c.set(a, 0);
  c.set(b, a.byteLength);
  return c;
}

let decoder = new TextDecoder()
let encoder = new TextEncoder()

const { Duplex } = require("readable-stream");

const EventEmitter = require('events')
class NodeClient extends Duplex {
  constructor(nclient) {
    super();
    this._control = new Promise((resolve)=>{
      this.__control_resolve__ = resolve;
    })
    this.connecting = true

    this.connect(nclient)
  }

  async connect(nclient) {
    let c = await nclient.dial((cid) => {
      this.connecting = false
      this.emit("connect");


      let ctrl = {}
      let req = new ConnData()
      req.setId(cid)
      nclient.socket.Connect(req, (conn) => { this.push(conn.getData()) }, ctrl)
        .then((msg) => {
          if (msg.code != 0) {
            this.emit("error", msg)
          } else {
            this.emit("end", msg)
            this.emit("close", msg)
          }
        })
        .catch((e)=>{thils.emit("error",e)})
        .finally(()=>ctrl.end())

      this.__control_resolve__(ctrl)
    })
  }

  _read(size) {
    // data is automatically pushed to buffer when the socket received chunk
  }
  async _write(chunk, encoding, callback) {
    const ctrl = await this._control;

    const req = new ConnData();
    req.setData(chunk)
    try {
      ctrl.write(req)
      callback(null)
    } catch (e) {
      callback(e)
    }
  }
  async _final(callback) {
    const ctrl = await this._control;
    try {
      ctrl.end()
      callback(null)
    } catch (e) {
      callback(e)
    }
  }

  setNoDelay() {
    // FIXME: remove this
    return true
  }
}

exports.createConnection = function(opts, callback) {
  if (typeof opts === 'string') {
    opts = {
      "path": opts
    }
  }
  if (!opts) opts = {
    host: "localhost"
  }

  let family
  let address
  if (opts.path) {
    family = "unix"
    address = opts.path
  } else if (opts.port && opts.host) {
    family = "tcp"
    address = `${opts.host}:${opts.port}`
  } else {
    throw `Only support the unix and tcp socket! Please the options.path or options.host and options.port field.`
  }
  return new NodeClient(new NSocketClient(family, address))
}
