text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.statementType = undefined;
  
  var _keys = require('babel-runtime/core-js/object/keys');
  
  var _keys2 = _interopRequireDefault(_keys);
  
  var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = require('babel-runtime/helpers/createClass');
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _integer = require('./integer');
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
    * A ResultSummary instance contains structured metadata for a {Result}.
    * @access public
    */
  var ResultSummary = function () {
    /**
     * @constructor
     * @param {string} statement - The statement this summary is for
     * @param {Object} parameters - Parameters for the statement
     * @param {Object} metadata - Statement metadata
     */
    function ResultSummary(statement, parameters, metadata) {
      (0, _classCallCheck3.default)(this, ResultSummary);
  
      /**
       * The statement and parameters this summary is for.
       * @type {{text: string, parameters: Object}}
       * @public
       */
      this.statement = { text: statement, parameters: parameters };
  
      /**
       * The type of statement executed. Can be "r" for read-only statement, "rw" for read-write statement,
       * "w" for write-only statement and "s" for schema-write statement.
       * String constants are available in {@link statementType} object.
       * @type {string}
       * @public
       */
      this.statementType = metadata.type;
  
      /**
       * Counters for operations the statement triggered.
       * @type {StatementStatistics}
       * @public
       */
      this.counters = new StatementStatistics(metadata.stats || {});
      //for backwards compatibility, remove in future version
      this.updateStatistics = this.counters;
  
      /**
       * This describes how the database will execute the statement.
       * Statement plan for the executed statement if available, otherwise undefined.
       * Will only be populated for queries that start with "EXPLAIN".
       * @type {Plan}
       */
      this.plan = metadata.plan || metadata.profile ? new Plan(metadata.plan || metadata.profile) : false;
  
      /**
       * This describes how the database did execute your statement. This will contain detailed information about what
       * each step of the plan did. Profiled statement plan for the executed statement if available, otherwise undefined.
       * Will only be populated for queries that start with "PROFILE".
       * @type {ProfiledPlan}
       * @public
       */
      this.profile = metadata.profile ? new ProfiledPlan(metadata.profile) : false;
  
      /**
       * An array of notifications that might arise when executing the statement. Notifications can be warnings about
       * problematic statements or other valuable information that can be presented in a client. Unlike failures
       * or errors, notifications do not affect the execution of a statement.
       * @type {Array<Notification>}
       * @public
       */
      this.notifications = this._buildNotifications(metadata.notifications);
  
      /**
       * The basic information of the server where the result is obtained from.
       * @type {ServerInfo}
       * @public
       */
      this.server = new ServerInfo(metadata.server);
  
      /**
       * The time it took the server to consume the result.
       * @type {number}
       * @public
       */
      this.resultConsumedAfter = metadata.result_consumed_after;
  
      /**
       * The time it took the server to make the result available for consumption in milliseconds.
       * @type {number}
       * @public
       */
      this.resultAvailableAfter = metadata.result_available_after;
    }
  
    (0, _createClass3.default)(ResultSummary, [{
      key: '_buildNotifications',
      value: function _buildNotifications(notifications) {
        if (!notifications) {
          return [];
        }
        return notifications.map(function (n) {
          return new Notification(n);
        });
      }
  
      /**
       * Check if the result summary has a plan
       * @return {boolean}
       */
  
    }, {
      key: 'hasPlan',
      value: function hasPlan() {
        return this.plan instanceof Plan;
      }
  
      /**
       * Check if the result summary has a profile
       * @return {boolean}
       */
  
    }, {
      key: 'hasProfile',
      value: function hasProfile() {
        return this.profile instanceof ProfiledPlan;
      }
    }]);
    return ResultSummary;
  }();
  
  /**
    * Class for execution plan received by prepending Cypher with EXPLAIN.
    * @access public
    */
  /**
   * Copyright (c) 2002-2018 "Neo4j,"
   * Neo4j Sweden AB [http://neo4j.com]
   *
   * This file is part of Neo4j.
   *
   * Licensed 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.
   */
  
  var Plan =
  /**
   * Create a Plan instance
   * @constructor
   * @param {Object} plan - Object with plan data
   */
  function Plan(plan) {
    (0, _classCallCheck3.default)(this, Plan);
  
    this.operatorType = plan.operatorType;
    this.identifiers = plan.identifiers;
    this.arguments = plan.args;
    this.children = plan.children ? plan.children.map(function (child) {
      return new Plan(child);
    }) : [];
  };
  
  /**
    * Class for execution plan received by prepending Cypher with PROFILE.
    * @access public
    */
  
  
  var ProfiledPlan =
  /**
   * Create a ProfiledPlan instance
   * @constructor
   * @param {Object} profile - Object with profile data
   */
  function ProfiledPlan(profile) {
    (0, _classCallCheck3.default)(this, ProfiledPlan);
  
    this.operatorType = profile.operatorType;
    this.identifiers = profile.identifiers;
    this.arguments = profile.args;
    this.dbHits = profile.args.DbHits.toInt();
    this.rows = profile.args.Rows.toInt();
    this.children = profile.children ? profile.children.map(function (child) {
      return new ProfiledPlan(child);
    }) : [];
  };
  
  /**
    * Get statistical information for a {@link Result}.
    * @access public
    */
  
  
  var StatementStatistics = function () {
    /**
     * Structurize the statistics
     * @constructor
     * @param {Object} statistics - Result statistics
     */
    function StatementStatistics(statistics) {
      var _this = this;
  
      (0, _classCallCheck3.default)(this, StatementStatistics);
  
      this._stats = {
        nodesCreated: 0,
        nodesDeleted: 0,
        relationshipsCreated: 0,
        relationshipsDeleted: 0,
        propertiesSet: 0,
        labelsAdded: 0,
        labelsRemoved: 0,
        indexesAdded: 0,
        indexesRemoved: 0,
        constraintsAdded: 0,
        constraintsRemoved: 0
      };
      (0, _keys2.default)(statistics).forEach(function (index) {
        //To camelCase
        _this._stats[index.replace(/(\-\w)/g, function (m) {
          return m[1].toUpperCase();
        })] = (0, _integer.isInt)(statistics[index]) ? statistics[index].toInt() : statistics[index];
      });
    }
  
    /**
     * Did the database get updated?
     * @return {boolean}
     */
  
  
    (0, _createClass3.default)(StatementStatistics, [{
      key: 'containsUpdates',
      value: function containsUpdates() {
        var _this2 = this;
  
        return (0, _keys2.default)(this._stats).reduce(function (last, current) {
          return last + _this2._stats[current];
        }, 0) > 0;
      }
  
      /**
       * @return {Number} - Number of nodes created.
       */
  
    }, {
      key: 'nodesCreated',
      value: function nodesCreated() {
        return this._stats.nodesCreated;
      }
  
      /**
       * @return {Number} - Number of nodes deleted.
       */
  
    }, {
      key: 'nodesDeleted',
      value: function nodesDeleted() {
        return this._stats.nodesDeleted;
      }
  
      /**
       * @return {Number} - Number of relationships created.
       */
  
    }, {
      key: 'relationshipsCreated',
      value: function relationshipsCreated() {
        return this._stats.relationshipsCreated;
      }
  
      /**
       * @return {Number} - Number of nodes deleted.
       */
  
    }, {
      key: 'relationshipsDeleted',
      value: function relationshipsDeleted() {
        return this._stats.relationshipsDeleted;
      }
  
      /**
       * @return {Number} - Number of properties set.
       */
  
    }, {
      key: 'propertiesSet',
      value: function propertiesSet() {
        return this._stats.propertiesSet;
      }
  
      /**
       * @return {Number} - Number of labels added.
       */
  
    }, {
      key: 'labelsAdded',
      value: function labelsAdded() {
        return this._stats.labelsAdded;
      }
  
      /**
       * @return {Number} - Number of labels removed.
       */
  
    }, {
      key: 'labelsRemoved',
      value: function labelsRemoved() {
        return this._stats.labelsRemoved;
      }
  
      /**
       * @return {Number} - Number of indexes added.
       */
  
    }, {
      key: 'indexesAdded',
      value: function indexesAdded() {
        return this._stats.indexesAdded;
      }
  
      /**
       * @return {Number} - Number of indexes removed.
       */
  
    }, {
      key: 'indexesRemoved',
      value: function indexesRemoved() {
        return this._stats.indexesRemoved;
      }
  
      /**
       * @return {Number} - Number of constraints added.
       */
  
    }, {
      key: 'constraintsAdded',
      value: function constraintsAdded() {
        return this._stats.constraintsAdded;
      }
  
      /**
       * @return {Number} - Number of constraints removed.
       */
  
    }, {
      key: 'constraintsRemoved',
      value: function constraintsRemoved() {
        return this._stats.constraintsRemoved;
      }
    }]);
    return StatementStatistics;
  }();
  
  /**
    * Class for Cypher notifications
    * @access public
    */
  
  
  var Notification = function () {
    /**
     * Create a Notification instance
     * @constructor
     * @param {Object} notification - Object with notification data
     */
    function Notification(notification) {
      (0, _classCallCheck3.default)(this, Notification);
  
      this.code = notification.code;
      this.title = notification.title;
      this.description = notification.description;
      this.severity = notification.severity;
      this.position = Notification._constructPosition(notification.position);
    }
  
    (0, _createClass3.default)(Notification, null, [{
      key: '_constructPosition',
      value: function _constructPosition(pos) {
        if (!pos) {
          return {};
        }
        return {
          offset: pos.offset.toInt(),
          line: pos.line.toInt(),
          column: pos.column.toInt()
        };
      }
    }]);
    return Notification;
  }();
  
  /**
    * Class for exposing server info from a result.
    * @access public
    */
  
  
  var ServerInfo =
  /**
   * Create a ServerInfo instance
   * @constructor
   * @param {Object} serverMeta - Object with serverMeta data
   */
  function ServerInfo(serverMeta) {
    (0, _classCallCheck3.default)(this, ServerInfo);
  
    if (serverMeta) {
      this.address = serverMeta.address;
      this.version = serverMeta.version;
    }
  };
  
  var statementType = {
    READ_ONLY: 'r',
    READ_WRITE: 'rw',
    WRITE_ONLY: 'w',
    SCHEMA_WRITE: 's'
  };
  
  exports.statementType = statementType;
  exports.default = ResultSummary;