// 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 url = require('url')

const httpUtil = require('../http/util')
const io = require('../io')
const { exec } = require('../io/exec')
const { Zip } = require('../io/zip')
const cmd = require('../lib/command')
const input = require('../lib/input')
const net = require('../net')
const portprober = require('../net/portprober')
const logging = require('../lib/logging')

const { getJavaPath, formatSpawnArgs } = require('./util')

/**
 * @typedef {(string|!Array<string|number|!stream.Stream|null|undefined>)}
 */
let StdIoOptions // eslint-disable-line

/**
 * @typedef {(string|!IThenable<string>)}
 */
let CommandLineFlag // eslint-disable-line

/**
 * A record object that defines the configuration options for a DriverService
 * instance.
 *
 * @record
 */
function ServiceOptions() {}

/**
 * Whether the service should only be accessed on this host's loopback address.
 *
 * @type {(boolean|undefined)}
 */
ServiceOptions.prototype.loopback

/**
 * The host name to access the server on. If this option is specified, the
 * {@link #loopback} option will be ignored.
 *
 * @type {(string|undefined)}
 */
ServiceOptions.prototype.hostname

/**
 * The port to start the server on (must be > 0). If the port is provided as a
 * promise, the service will wait for the promise to resolve before starting.
 *
 * @type {(number|!IThenable<number>)}
 */
ServiceOptions.prototype.port

/**
 * The arguments to pass to the service. If a promise is provided, the service
 * will wait for it to resolve before starting.
 *
 * @type {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)}
 */
ServiceOptions.prototype.args

/**
 * The base path on the server for the WebDriver wire protocol (e.g. '/wd/hub').
 * Defaults to '/'.
 *
 * @type {(string|undefined|null)}
 */
ServiceOptions.prototype.path

/**
 * The environment variables that should be visible to the server process.
 * Defaults to inheriting the current process's environment.
 *
 * @type {(Object<string, string>|undefined)}
 */
ServiceOptions.prototype.env

/**
 * IO configuration for the spawned server process. For more information, refer
 * to the documentation of `child_process.spawn`.
 *
 * @type {(StdIoOptions|undefined)}
 * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
 */
ServiceOptions.prototype.stdio

/**
 * Manages the life and death of a native executable WebDriver server.
 *
 * It is expected that the driver server implements the
 * https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol.
 * Furthermore, the managed server should support multiple concurrent sessions,
 * so that this class may be reused for multiple clients.
 */
class DriverService {
  /**
   * @param {string} executable Path to the executable to run.
   * @param {!ServiceOptions} options Configuration options for the service.
   */
  constructor(executable, options) {
    /** @private @const */
    this.log_ = logging.getLogger('webdriver.DriverService')
    /** @private {string} */
    this.executable_ = executable

    /** @private {boolean} */
    this.loopbackOnly_ = !!options.loopback

    /** @private {(string|undefined)} */
    this.hostname_ = options.hostname

    /** @private {(number|!IThenable<number>)} */
    this.port_ = options.port

    /**
     * @private {!(Array<CommandLineFlag>|
     *             IThenable<!Array<CommandLineFlag>>)}
     */
    this.args_ = options.args

    /** @private {string} */
    this.path_ = options.path || '/'

    /** @private {!Object<string, string>} */
    this.env_ = options.env || process.env

    /**
     * @private {(string|!Array<string|number|!stream.Stream|null|undefined>)}
     */
    this.stdio_ = options.stdio || 'ignore'

    /**
     * A promise for the managed subprocess, or null if the server has not been
     * started yet. This promise will never be rejected.
     * @private {Promise<!exec.Command>}
     */
    this.command_ = null

    /**
     * Promise that resolves to the server's address or null if the server has
     * not been started. This promise will be rejected if the server terminates
     * before it starts accepting WebDriver requests.
     * @private {Promise<string>}
     */
    this.address_ = null
  }

  getExecutable() {
    return this.executable_
  }

  setExecutable(value) {
    this.executable_ = value
  }

  /**
   * @return {!Promise<string>} A promise that resolves to the server's address.
   * @throws {Error} If the server has not been started.
   */
  address() {
    if (this.address_) {
      return this.address_
    }
    throw Error('Server has not been started.')
  }

  /**
   * Returns whether the underlying process is still running. This does not take
   * into account whether the process is in the process of shutting down.
   * @return {boolean} Whether the underlying service process is running.
   */
  isRunning() {
    return !!this.address_
  }

  /**
   * Starts the server if it is not already running.
   * @param {number=} opt_timeoutMs How long to wait, in milliseconds, for the
   *     server to start accepting requests. Defaults to 30 seconds.
   * @return {!Promise<string>} A promise that will resolve to the server's base
   *     URL when it has started accepting requests. If the timeout expires
   *     before the server has started, the promise will be rejected.
   */
  start(opt_timeoutMs) {
    if (this.address_) {
      return this.address_
    }

    const timeout = opt_timeoutMs || DriverService.DEFAULT_START_TIMEOUT_MS
    const self = this

    let resolveCommand
    this.command_ = new Promise((resolve) => (resolveCommand = resolve))

    this.address_ = new Promise((resolveAddress, rejectAddress) => {
      resolveAddress(
        Promise.resolve(this.port_).then((port) => {
          if (port <= 0) {
            throw Error('Port must be > 0: ' + port)
          }

          return resolveCommandLineFlags(this.args_).then((args) => {
            const command = exec(self.executable_, {
              args: args,
              env: self.env_,
              stdio: self.stdio_,
            })

            resolveCommand(command)

            const earlyTermination = command.result().then(function (result) {
              const error =
                result.code == null
                  ? Error('Server was killed with ' + result.signal)
                  : Error('Server terminated early with status ' + result.code)
              rejectAddress(error)
              self.address_ = null
              self.command_ = null
              throw error
            })

            let hostname = self.hostname_
            if (!hostname) {
              hostname =
                (!self.loopbackOnly_ && net.getAddress()) ||
                net.getLoopbackAddress()
            }

            const serverUrl = url.format({
              protocol: 'http',
              hostname: hostname,
              port: port + '',
              pathname: self.path_,
            })

            return new Promise((fulfill, reject) => {
              let cancelToken = earlyTermination.catch((e) =>
                reject(Error(e.message))
              )

              httpUtil.waitForServer(serverUrl, timeout, cancelToken).then(
                (_) => fulfill(serverUrl),
                (err) => {
                  if (err instanceof httpUtil.CancellationError) {
                    fulfill(serverUrl)
                  } else {
                    reject(err)
                  }
                }
              )
            })
          })
        })
      )
    })

    return this.address_
  }

  /**
   * Stops the service if it is not currently running. This function will kill
   * the server immediately. To synchronize with the active control flow, use
   * {@link #stop()}.
   * @return {!Promise} A promise that will be resolved when the server has been
   *     stopped.
   */
  kill() {
    if (!this.address_ || !this.command_) {
      return Promise.resolve() // Not currently running.
    }
    let cmd = this.command_
    this.address_ = null
    this.command_ = null
    return cmd.then((c) => c.kill('SIGTERM'))
  }
}

/**
 * @param {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)} args
 * @return {!Promise<!Array<string>>}
 */
function resolveCommandLineFlags(args) {
  // Resolve the outer array, then the individual flags.
  return Promise.resolve(args).then(
    /** !Array<CommandLineFlag> */ (args) => Promise.all(args)
  )
}

/**
 * The default amount of time, in milliseconds, to wait for the server to
 * start.
 * @const {number}
 */
DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000

/**
 * Creates {@link DriverService} objects that manage a WebDriver server in a
 * child process.
 */
DriverService.Builder = class {
  /**
   * @param {string} exe Path to the executable to use. This executable must
   *     accept the `--port` flag for defining the port to start the server on.
   * @throws {Error} If the provided executable path does not exist.
   */
  constructor(exe) {
    /** @private @const {string} */
    this.exe_ = exe

    /** @private {!ServiceOptions} */
    this.options_ = {
      args: [],
      port: 0,
      env: null,
      stdio: 'ignore',
    }
  }

  /**
   * Define additional command line arguments to use when starting the server.
   *
   * @param {...CommandLineFlag} var_args The arguments to include.
   * @return {!THIS} A self reference.
   * @this {THIS}
   * @template THIS
   */
  addArguments(...arguments_) {
    this.options_.args = this.options_.args.concat(arguments_)
    return this
  }

  /**
   * Sets the host name to access the server on. If specified, the
   * {@linkplain #setLoopback() loopback} setting will be ignored.
   *
   * @param {string} hostname
   * @return {!DriverService.Builder} A self reference.
   */
  setHostname(hostname) {
    this.options_.hostname = hostname
    return this
  }

  /**
   * Sets whether the service should be accessed at this host's loopback
   * address.
   *
   * @param {boolean} loopback
   * @return {!DriverService.Builder} A self reference.
   */
  setLoopback(loopback) {
    this.options_.loopback = loopback
    return this
  }

  /**
   * Sets the base path for WebDriver REST commands (e.g. "/wd/hub").
   * By default, the driver will accept commands relative to "/".
   *
   * @param {?string} basePath The base path to use, or `null` to use the
   *     default.
   * @return {!DriverService.Builder} A self reference.
   */
  setPath(basePath) {
    this.options_.path = basePath
    return this
  }

  /**
   * Sets the port to start the server on.
   *
   * @param {number} port The port to use, or 0 for any free port.
   * @return {!DriverService.Builder} A self reference.
   * @throws {Error} If an invalid port is specified.
   */
  setPort(port) {
    if (port < 0) {
      throw Error(`port must be >= 0: ${port}`)
    }
    this.options_.port = port
    return this
  }

  /**
   * Defines the environment to start the server under. This setting will be
   * inherited by every browser session started by the server. By default, the
   * server will inherit the enviroment of the current process.
   *
   * @param {(Map<string, string>|Object<string, string>|null)} env The desired
   *     environment to use, or `null` if the server should inherit the
   *     current environment.
   * @return {!DriverService.Builder} A self reference.
   */
  setEnvironment(env) {
    if (env instanceof Map) {
      let tmp = {}
      env.forEach((value, key) => (tmp[key] = value))
      env = tmp
    }
    this.options_.env = env
    return this
  }

  /**
   * IO configuration for the spawned server process. For more information,
   * refer to the documentation of `child_process.spawn`.
   *
   * @param {StdIoOptions} config The desired IO configuration.
   * @return {!DriverService.Builder} A self reference.
   * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
   */
  setStdio(config) {
    this.options_.stdio = config
    return this
  }

  /**
   * Creates a new DriverService using this instance's current configuration.
   *
   * @return {!DriverService} A new driver service.
   */
  build() {
    let port = this.options_.port || portprober.findFreePort()
    let args = Promise.resolve(port).then((port) => {
      return this.options_.args.concat('--port=' + port)
    })

    let options =
      /** @type {!ServiceOptions} */
      (Object.assign({}, this.options_, { args, port }))
    return new DriverService(this.exe_, options)
  }
}

/**
 * Manages the life and death of the
 * <a href="https://www.selenium.dev/downloads/">
 * standalone Selenium server</a>.
 */
class SeleniumServer extends DriverService {
  /**
   * @param {string} jar Path to the Selenium server jar.
   * @param {SeleniumServer.Options=} opt_options Configuration options for the
   *     server.
   * @throws {Error} If the path to the Selenium jar is not specified or if an
   *     invalid port is specified.
   */
  constructor(jar, opt_options) {
    if (!jar) {
      throw Error('Path to the Selenium jar not specified')
    }

    const options = opt_options || {}

    if (options.port < 0) {
      throw Error('Port must be >= 0: ' + options.port)
    }

    let port = options.port || portprober.findFreePort()
    let args = Promise.all([
      port,
      options.jvmArgs || [],
      options.args || [],
    ]).then((resolved) => {
      let port = resolved[0]
      let jvmArgs = resolved[1]
      let args = resolved[2]

      const fullArgsList = jvmArgs
        .concat('-jar', jar, '-port', port)
        .concat(args)

      return formatSpawnArgs(jar, fullArgsList)
    })

    const java = getJavaPath()

    super(java, {
      loopback: options.loopback,
      port: port,
      args: args,
      path: '/wd/hub',
      env: options.env,
      stdio: options.stdio,
    })
  }
}

/**
 * A record object describing configuration options for a {@link SeleniumServer}
 * instance.
 *
 * @record
 */
SeleniumServer.Options = class {
  constructor() {
    /**
     * Whether the server should only be accessible on this host's loopback
     * address.
     *
     * @type {(boolean|undefined)}
     */
    this.loopback

    /**
     * The port to start the server on (must be > 0). If the port is provided as
     * a promise, the service will wait for the promise to resolve before
     * starting.
     *
     * @type {(number|!IThenable<number>)}
     */
    this.port

    /**
     * The arguments to pass to the service. If a promise is provided,
     * the service will wait for it to resolve before starting.
     *
     * @type {!(Array<string>|IThenable<!Array<string>>)}
     */
    this.args

    /**
     * The arguments to pass to the JVM. If a promise is provided,
     * the service will wait for it to resolve before starting.
     *
     * @type {(!Array<string>|!IThenable<!Array<string>>|undefined)}
     */
    this.jvmArgs

    /**
     * The environment variables that should be visible to the server
     * process. Defaults to inheriting the current process's environment.
     *
     * @type {(!Object<string, string>|undefined)}
     */
    this.env

    /**
     * IO configuration for the spawned server process. If unspecified, IO will
     * be ignored.
     *
     * @type {(string|!Array<string|number|!stream.Stream|null|undefined>|
     *         undefined)}
     * @see <https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_options_stdio>
     */
    this.stdio
  }
}

/**
 * A {@link webdriver.FileDetector} that may be used when running
 * against a remote
 * [Selenium server](https://www.selenium.dev/downloads/).
 *
 * When a file path on the local machine running this script is entered with
 * {@link webdriver.WebElement#sendKeys WebElement#sendKeys}, this file detector
 * will transfer the specified file to the Selenium server's host; the sendKeys
 * command will be updated to use the transferred file's path.
 *
 * __Note:__ This class depends on a non-standard command supported on the
 * Java Selenium server. The file detector will fail if used with a server that
 * only supports standard WebDriver commands (such as the ChromeDriver).
 *
 * @final
 */
class FileDetector extends input.FileDetector {
  /**
   * Prepares a `file` for use with the remote browser. If the provided path
   * does not reference a normal file (i.e. it does not exist or is a
   * directory), then the promise returned by this method will be resolved with
   * the original file path. Otherwise, this method will upload the file to the
   * remote server, which will return the file's path on the remote system so
   * it may be referenced in subsequent commands.
   *
   * @override
   */
  handleFile(driver, file) {
    return io.stat(file).then(
      function (stats) {
        if (stats.isDirectory()) {
          return file // Not a valid file, return original input.
        }

        let zip = new Zip()
        return zip
          .addFile(file)
          .then(() => zip.toBuffer())
          .then((buf) => buf.toString('base64'))
          .then((encodedZip) => {
            let command = new cmd.Command(cmd.Name.UPLOAD_FILE).setParameter(
              'file',
              encodedZip
            )
            return driver.execute(command)
          })
      },
      function (err) {
        if (err.code === 'ENOENT') {
          return file // Not a file; return original input.
        }
        throw err
      }
    )
  }
}

// PUBLIC API

module.exports = {
  DriverService,
  FileDetector,
  SeleniumServer,
  // Exported for API docs.
  ServiceOptions,
}
