"use strict";
var util = require('util');
/** @module types */

/**
 * Creates a new instance of ResultSet.
 * @class
 * @classdesc Represents the result of a query.
 * @param {Object} response
 * @param {String} host
 * @param {Object} triedHosts
 * @param {Number} consistency
 * @constructor
 */
function ResultSet(response, host, triedHosts, consistency) {
  /**
   * Information on the execution of a successful query:
   * @member {Object}
   * @property {Number} achievedConsistency The consistency level that has been actually achieved by the query.
   * @property {String} queriedHost The Cassandra host that coordinated this query.
   * @property {Object} triedHosts Gets the associative array of host that were queried before getting a valid response,
   * being the last host the one that replied correctly.
   * @property {Uuid} traceId Identifier of the trace session.
   * @property {Array.<string>} warnings Warning messages generated by the server when executing the query.
   */
  this.info = {
    queriedHost: host,
    triedHosts: triedHosts,
    achievedConsistency: consistency,
    traceId: null,
    warnings: null,
    customPayload: null
  };
  if (response.flags) {
    this.info.traceId = response.flags.traceId;
    this.info.warnings = response.flags.warnings;
    this.info.customPayload = response.flags.customPayload;
  }
  /**
   * Gets an array rows returned by the query, in case the result was buffered.
   * @type {Array.<Row>}
   */
  this.rows = response.rows;
  /**
   * Gets the row length of the result, regardless if the result has been buffered or not
   * @type {Number}
   */
  this.rowLength = this.rows ? this.rows.length : response.rowLength;
  /**
   * Gets the columns returned in this ResultSet.
   * @type {Array.<{name, type}>}
   * @default null
   */
  this.columns = null;
  /**
   * A string token representing the current page state of query. It can be used in the following executions to
   * continue paging and retrieve the remained of the result for the query.
   * @type String
   * @default null
   */
  this.pageState = null;
  /**
   * Method used to manually fetch the next page of results.
   * This method is only exposed when using the {@link Client#eachRow} method and there are more rows available in
   * following pages.
   * @type Function
   */
  this.nextPage = undefined;

  var meta = response.meta;
  if (meta) {
    this.columns = meta.columns;
    if (meta.pageState) {
      this.pageState = meta.pageState.toString('hex');
    }
  }
  if (response.id) {
    // internal properties for prepared responses
    Object.defineProperty(this, 'id', { value: response.id, enumerable: false});
    Object.defineProperty(this, 'meta', { value: response.meta, enumerable: false});
  }
  else if (this.pageState !== null) {
    // page state was exposed in version 1 via result.meta.pageState as a Buffer.
    // it was not specified in the upgrade guide to v2, we must wait for a next major to remove it
    Object.defineProperty(this, 'meta', { value: response.meta, enumerable: false});
  }
}

/**
 * Returns the first row or null if the result rows are empty
 */
ResultSet.prototype.first = function () {
  if (this.rows && this.rows.length) {
    return this.rows[0];
  }
  return null;
};

ResultSet.prototype.getPageState = function () {
  // backward-compatibility
  return this.pageState;
};

ResultSet.prototype.getColumns = function () {
  // backward-compatibility
  return this.columns;
};

module.exports = ResultSet;