/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 events = require('events');
const RequestTracker = require('./request-tracker');
const errors = require('../errors');
const { format } = require('util');

const nanosToMillis = 1000000;
const defaultMessageMaxQueryLength = 500;
const defaultMaxParameterValueLength = 50;
const defaultMaxErrorStackTraceLength = 200;

/**
 * A request tracker that logs the requests executed through the session, according to a set of
 * configurable options.
 * @implements {module:tracker~RequestTracker}
 * @alias module:tracker~RequestLogger
 * @example <caption>Logging slow queries</caption>
 * const requestLogger = new RequestLogger({ slowThreshold: 1000 });
 * requestLogger.emitter.on('show', message => console.log(message));
 * // Add the requestLogger to the client options
 * const client = new Client({ contactPoints, requestTracker: requestLogger });
 */
class RequestLogger extends RequestTracker {

  /**
   * Creates a new instance of {@link RequestLogger}.
   * @param {Object} options
   * @param {Number} [options.slowThreshold] The threshold in milliseconds beyond which queries are considered 'slow'
   * and logged as such by the driver.
   * @param {Number} [options.requestSizeThreshold] The threshold in bytes beyond which requests are considered 'large'
   * and logged as such by the driver.
   * @param {Boolean} [options.logNormalRequests] Determines whether it should emit 'normal' events for every
   * EXECUTE, QUERY and BATCH request executed successfully, useful only for debugging. This option can be modified
   * after the client is connected using the property {@link RequestLogger#logNormalRequests}.
   * @param {Boolean} [options.logErroredRequests] Determines whether it should emit 'failure' events for every
   * EXECUTE, QUERY and BATCH request execution that resulted in an error. This option can be modified
   * after the client is connected using the property {@link RequestLogger#logErroredRequests}.
   * @param {Number} [options.messageMaxQueryLength] The maximum amount of characters that are logged from the query
   * portion of the message. Defaults to 500.
   * @param {Number} [options.messageMaxParameterValueLength] The maximum amount of characters of each query parameter
   * value that will be included in the message. Defaults to 50.
   * @param {Number} [options.messageMaxErrorStackTraceLength] The maximum amount of characters of the stack trace
   * that will be included in the message. Defaults to 200.
   */
  constructor(options) {
    super();
    if (!options) {
      throw new errors.ArgumentError('RequestLogger options parameter is required');
    }

    this._options = options;

    /**
     * Determines whether it should emit 'normal' events for every EXECUTE, QUERY and BATCH request executed
     * successfully, useful only for debugging
     * @type {Boolean}
     */
    this.logNormalRequests = this._options.logNormalRequests;

    /**
     * Determines whether it should emit 'failure' events for every EXECUTE, QUERY and BATCH request execution that
     * resulted in an error
     * @type {Boolean}
     */
    this.logErroredRequests = this._options.logErroredRequests;

    /**
     * The object instance that emits <code>'slow'</code>, <code>'large'</code>, <code>'normal'</code> and
     * <code>'failure'</code> events.
     * @type {EventEmitter}
     */
    this.emitter = new events.EventEmitter();
  }

  /**
   * Logs message if request execution was deemed too slow, large or if normal requests are logged.
   * @override
   */
  onSuccess(host, query, parameters, execOptions, requestLength, responseLength, latency) {
    if (this._options.slowThreshold > 0 && toMillis(latency) > this._options.slowThreshold) {
      this._logSlow(host, query, parameters, execOptions, requestLength, responseLength, latency);
    }
    else if (this._options.requestSizeThreshold > 0 && requestLength > this._options.requestSizeThreshold) {
      this._logLargeRequest(host, query, parameters, execOptions, requestLength, responseLength, latency);
    }
    else if (this.logNormalRequests) {
      this._logNormalRequest(host, query, parameters, execOptions, requestLength, responseLength, latency);
    }
  }

  /**
   * Logs message if request execution was too large and/or encountered an error.
   * @override
   */
  onError(host, query, parameters, execOptions, requestLength, err, latency) {
    if (this._options.requestSizeThreshold > 0 && requestLength > this._options.requestSizeThreshold) {
      this._logLargeErrorRequest(host, query, parameters, execOptions, requestLength, err, latency);
    }
    else if (this.logErroredRequests) {
      this._logErrorRequest(host, query, parameters, execOptions, requestLength, err, latency);
    }
  }

  _logSlow(host, query, parameters, execOptions, requestLength, responseLength, latency) {
    const message = format('[%s] Slow request, took %d ms (%s): %s', host.address, Math.floor(toMillis(latency)),
      getPayloadSizes(requestLength, responseLength), getStatementInfo(query, parameters, execOptions, this._options));
    this.emitter.emit('slow', message);
  }

  _logLargeRequest(host, query, parameters, execOptions, requestLength, responseLength, latency) {
    const message = format('[%s] Request exceeded length, %s (took %d ms): %s', host.address,
      getPayloadSizes(requestLength, responseLength), ~~toMillis(latency),
      getStatementInfo(query, parameters, execOptions, this._options));
    this.emitter.emit('large', message);
  }

  _logNormalRequest(host, query, parameters, execOptions, requestLength, responseLength, latency) {
    const message = format('[%s] Request completed normally, took %d ms (%s): %s', host.address, ~~toMillis(latency),
      getPayloadSizes(requestLength, responseLength), getStatementInfo(query, parameters, execOptions, this._options));
    this.emitter.emit('normal', message);
  }

  _logLargeErrorRequest(host, query, parameters, execOptions, requestLength, err, latency) {
    const maxStackTraceLength = this._options.messageMaxErrorStackTraceLength || defaultMaxErrorStackTraceLength;
    const message = format('[%s] Request exceeded length and execution failed, %s (took %d ms): %s; error: %s',
      host.address, getPayloadSizes(requestLength), ~~toMillis(latency),
      getStatementInfo(query, parameters, execOptions, this._options), err.stack.substr(0, maxStackTraceLength));

    // Use 'large' event and not 'failure' as this log is caused by exceeded length
    this.emitter.emit('large', message);
  }

  _logErrorRequest(host, query, parameters, execOptions, requestLength, err, latency) {
    const maxStackTraceLength = this._options.messageMaxErrorStackTraceLength || defaultMaxErrorStackTraceLength;
    const message = format('[%s] Request execution failed, took %d ms (%s): %s; error: %s', host.address,
      ~~toMillis(latency), getPayloadSizes(requestLength),
      getStatementInfo(query, parameters, execOptions, this._options), err.stack.substr(0, maxStackTraceLength));

    // Avoid using 'error' as its a special event
    this.emitter.emit('failure', message);
  }
}

function toMillis(latency) {
  return latency[0] * 1000 + latency[1] / nanosToMillis;
}

function getStatementInfo(query, parameters, execOptions, options) {
  const maxQueryLength = options.messageMaxQueryLength || defaultMessageMaxQueryLength;
  const maxParameterLength = options.messageMaxParameterValueLength || defaultMaxParameterValueLength;

  if (Array.isArray(query)) {
    return getBatchStatementInfo(query, execOptions, maxQueryLength, maxParameterLength);
  }

  // String concatenation is usually faster than Array#join() in V8
  let message = query.substr(0, maxQueryLength);
  const remaining = maxQueryLength - message.length - 1;
  message += getParametersInfo(parameters, remaining, maxParameterLength);

  if (!execOptions.isPrepared()) {
    // This part of the message is not accounted for in "maxQueryLength"
    message += ' (not prepared)';
  }

  return message;
}

function getBatchStatementInfo(queries, execOptions, maxQueryLength, maxParameterLength) {
  // This part of the message is not accounted for in "maxQueryLength"
  let message = (execOptions.isBatchLogged() ? 'LOGGED ' : '') + 'BATCH w/ ' + queries.length +
    (!execOptions.isPrepared() ? ' not prepared' : '') + ' queries (';
  let remaining = maxQueryLength;
  let i;

  for (i = 0; i < queries.length && remaining > 0; i++) {
    let q = queries[i];
    const params = q.params;
    if (typeof q !== 'string') {
      q = q.query;
    }

    if (i > 0) {
      message += ',';
      remaining--;
    }

    const queryLength = Math.min(remaining, q.length);
    message += q.substr(0, queryLength);
    remaining -= queryLength;

    if (remaining <= 0) {
      break;
    }

    const parameters = getParametersInfo(params, remaining, maxParameterLength);
    remaining -= parameters.length;
    message += parameters;
  }

  message += i < queries.length ? ',...)' : ')';
  return message;
}

function getParametersInfo(params, remaining, maxParameterLength) {
  if (remaining <= 3) {
    // We need at least 3 chars to describe the parameters
    // its OK to add more chars in an effort to be descriptive
    return ' [...]';
  }

  if (!params) {
    return ' []';
  }

  let paramStringifier = (index, length) => formatParam(params[index], length);
  if (!Array.isArray(params)) {
    const obj = params;
    params = Object.keys(params);
    paramStringifier = (index, length) => {
      const key = params[index];
      let result = key.substr(0, length);
      const rem = length - result.length - 1;
      if (rem <= 0) {
        return result;
      }
      result += ":" + formatParam(obj[key], rem);
      return result;
    };
  }

  let message = ' [';
  let i;
  for (i = 0; remaining > 0 && i < params.length; i++) {
    if (i > 0) {
      message += ',';
      remaining--;
    }

    const paramString = paramStringifier(i, Math.min(maxParameterLength, remaining));
    remaining -= paramString.length;
    message += paramString;
  }

  if (i < params.length) {
    message += '...';
  }

  message += ']';
  return message;
}

function formatParam(value, maxLength) {
  if (value === undefined) {
    return 'undefined';
  }

  if (value === null) {
    return 'null';
  }

  return value.toString().substr(0, maxLength);
}

function getPayloadSizes(requestLength, responseLength) {
  let message = 'request size ' + formatSize(requestLength);
  if (responseLength !== undefined) {
    message += ' / response size ' + formatSize(responseLength);
  }
  return message;
}

function formatSize(length) {
  return length > 1000 ? Math.round(length / 1024) + ' KB' : length + ' bytes';
}

module.exports = RequestLogger;