import { NSocket, ConnID, ConnData, SocketAddress } from "./lib/socket"
export { NSocket, ConnID, ConnData, SocketAddress }

/**
 * @name NSocketServe
 * @class
 */
export class NSocketServe {
  /**
   *
   * create a new listner object
   * @param {} protocol
   * @param {} address
   * @param {} callback
   * @returns {}
   *
   * @example
   * let decoder = new TextDecoder()
   * et encoder = new TextEncoder()
   * function Serve() {
   * let lis = new NSocketServe("tcp", "127.0.0.1:9080")
   * lis.serve((data, control) => {
   *   console.log("Serve Receive Msg: ")
   *   console.log(decoder.decode(data))
   *
   *   let req = new ConnData()
   *   req.setData(encoder.encode(`HTTP/1.1 200 OK\r\n\r\n Serve Send: ${new Date()}`))
   *   control.write(req)
   *  })
   * }
   * // Serve() // terminal: exec `curl -I http://127.0.0.1:9080/` will return the right info.
   *
   */
  constructor(protocol, address) {
    this.protocol = protocol
    this.address = address

    this.control = {}
    this.socket = new NSocket()
  }

  listen(callback) {
    let req = new SocketAddress()
    req.setProtocol(this.protocol)
    req.setAddress(this.address)

    return this.socket.Listen(req, (msg) => {
      callback(msg.getId())
    }, this.control)
  }

  close () {
    this.control.cancel && this.control.cancel()
  }

  readWriteCloseConn(id, control, callback) {
    let req = new ConnData()
    req.setId(id)

    return this.socket.ReadWriteCloseConn(req, (msg) => {
      callback(msg.getData(), control)
    }, control)
  }

  /**
   * serve listen the socket and call callback when appear a new connection
   * @param {} callback
   * @returns {}
   *
   */
  serve(callback) {
    return this.listen((id) => {
      let c = {}
      this.readWriteCloseConn(id, c, callback)
    })
  }
}

// Example:
// let decoder = new TextDecoder()
// let encoder = new TextEncoder()
// function Connection(control) {
//   let client = new NSocketClient("tcp", "127.0.0.1:9080")
//   client.connection(control, (data) => {
//     console.log("Client Receive Msg: ")
//     console.log(decoder.decode(data))
//   })
// }
//
// function RequestHEAD(control) {
//   let req = new ConnData()
//   req.setData(encoder.encode(`HEAD / HTTP/1.1
// Host: 127.0.0.1:9080
// User-Agent: curl/7.72.0
// Accept: */*`))
//   control.write(req)
// }
//
// let control = {}
// Connection(control)
// RequestHEAD(control)
export class NSocketClient {
  constructor(protocol, address) {
    this.protocol = protocol
    this.address = address

    this.socket = new NSocket()
    this.control = {}
  }

  dial(callback) {
    let req = new SocketAddress()
    req.setProtocol(this.protocol)
    req.setAddress(this.address)

    return this.socket.Dial(req, (msg) => {
      let id = msg.getId()
      callback(id)
    }, this.control)
  }

  close () {
    this.control.cancel && this.control.cancel()
  }

  connect(id, control, callback) {
    let req = new ConnData()
    req.setId(id)

    return this.socket.Connect(req, (msg) => {
      callback(msg.getData())
    }, control)
  }

  connection(control, callback) {
    return this.dial((id) => {
      control['promise'] = this.connect(id, control, callback)
    })
  }
}
