// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you 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.

'use strict'

const assert = require('node:assert')
const http = require('node:http')
const url = require('node:url')

const net = require('selenium-webdriver/net')
const portprober = require('selenium-webdriver/net/portprober')
const promise = require('selenium-webdriver').promise

/**
 * Encapsulates a simple HTTP server for testing. The {@code onrequest}
 * function should be overridden to define request handling behavior.
 * @param {function(!http.ServerRequest, !http.ServerResponse)} requestHandler
 *     The request handler for the server.
 * @constructor
 */
let Server = function (requestHandler) {
  let server = http.createServer(function (req, res) {
    requestHandler(req, res)
  })

  server.on('connection', function (stream) {
    stream.setTimeout(4000)
  })

  /** @typedef {{port: number, address: string, family: string}} */
  let Host // eslint-disable-line

  /**
   * Starts the server on the given port. If no port, or 0, is provided,
   * the server will be started on a random port.
   * @param {number=} opt_port The port to start on.
   * @return {!Promise<Host>} A promise that will resolve
   *     with the server host when it has fully started.
   */
  this.start = function (opt_port) {
    assert(typeof opt_port !== 'function', 'start invoked with function, not port (mocha callback)?')
    const port = opt_port || portprober.findFreePort('127.0.0.1')
    return Promise.resolve(port)
      .then((port) => {
        return promise.checkedNodeCall(server.listen.bind(server, port, '127.0.0.1'))
      })
      .then(function () {
        return server.address()
      })
  }

  /**
   * Stops the server.
   * @return {!Promise} A promise that will resolve when the
   *     server has closed all connections.
   */
  this.stop = function () {
    return new Promise((resolve) => server.close(resolve))
  }

  /**
   * @return {Host} This server's host info.
   * @throws {Error} If the server is not running.
   */
  this.address = function () {
    const addr = server.address()
    if (!addr) {
      throw Error('There server is not running!')
    }
    return addr
  }

  /**
   * return {string} The host:port of this server.
   * @throws {Error} If the server is not running.
   */
  this.host = function () {
    return net.getLoopbackAddress() + ':' + this.address().port
  }

  /**
   * Formats a URL for this server.
   * @param {string=} opt_pathname The desired pathname on the server.
   * @return {string} The formatted URL.
   * @throws {Error} If the server is not running.
   */
  this.url = function (opt_pathname) {
    const addr = this.address()
    const pathname = opt_pathname || ''
    return url.format({
      protocol: 'http',
      hostname: net.getLoopbackAddress(),
      port: addr.port,
      pathname: pathname,
    })
  }
}

// PUBLIC API

exports.Server = Server
