// Copyright (C) 2017 The Android Open Source Project
//
// 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.
(function(window) {
  'use strict';

  // Prevent redefinition.
  if (window.GrReviewerUpdatesParser) { return; }

  function GrReviewerUpdatesParser(change) {
    // TODO (viktard): Polyfill Object.assign for IE.
    this.result = Object.assign({}, change);
    this._lastState = {};
  };

  GrReviewerUpdatesParser.parse = function(change) {
    if (!change ||
        !change.messages ||
        !change.reviewer_updates ||
        !change.reviewer_updates.length) {
      return change;
    }
    var parser = new GrReviewerUpdatesParser(change);
    parser._filterRemovedMessages();
    parser._groupUpdates();
    parser._formatUpdates();
    return parser.result;
  };

  GrReviewerUpdatesParser.REVIEWER_UPDATE_THRESHOLD_MILLIS = 6000;

  GrReviewerUpdatesParser.prototype.result = null;
  GrReviewerUpdatesParser.prototype._batch = null;
  GrReviewerUpdatesParser.prototype._updateItems = null;
  GrReviewerUpdatesParser.prototype._lastState = null;

  /**
   * Removes messages that describe removed reviewers, since reviewer_updates
   * are used.
   */
  GrReviewerUpdatesParser.prototype._filterRemovedMessages = function() {
    this.result.messages = this.result.messages.filter(function(message) {
      return message.tag !== 'autogenerated:gerrit:deleteReviewer';
    });
  };

  /**
   * Is a part of _groupUpdates(). Creates a new batch of updates.
   * @param {Object} update instance of ReviewerUpdateInfo
   */
  GrReviewerUpdatesParser.prototype._startBatch = function(update) {
    this._updateItems = [];
    return {
      author: update.updated_by,
      date: update.updated,
      type: 'REVIEWER_UPDATE',
    };
  };

  /**
   * Is a part of _groupUpdates(). Validates current batch:
   * - filters out updates that don't change reviewer state.
   * - updates current reviewer state.
   * @param {Object} update instance of ReviewerUpdateInfo
   */
  GrReviewerUpdatesParser.prototype._completeBatch = function(update) {
    var items = [];
    for (var accountId in this._updateItems) {
      if (!this._updateItems.hasOwnProperty(accountId)) continue;
      var updateItem = this._updateItems[accountId];
      if (this._lastState[accountId] !== updateItem.state) {
        this._lastState[accountId] = updateItem.state;
        items.push(updateItem);
      }
    }
    if (items.length) {
      this._batch.updates = items;
    }
  };

  /**
   * Groups reviewer updates. Sequential updates are grouped if:
   * - They were performed within short timeframe (6 seconds)
   * - Made by the same person
   * - Non-change updates are discarded within a group
   * - Groups with no-change updates are discarded (eg CC -> CC)
   */
  GrReviewerUpdatesParser.prototype._groupUpdates = function() {
    var updates = this.result.reviewer_updates;
    var newUpdates = updates.reduce(function(newUpdates, update) {
      if (!this._batch) {
        this._batch = this._startBatch(update);
      }
      var updateDate = util.parseDate(update.updated).getTime();
      var batchUpdateDate = util.parseDate(this._batch.date).getTime();
      var reviewerId = update.reviewer._account_id.toString();
      if (updateDate - batchUpdateDate >
          GrReviewerUpdatesParser.REVIEWER_UPDATE_THRESHOLD_MILLIS ||
          update.updated_by._account_id !== this._batch.author._account_id) {
        // Next sequential update should form new group.
        this._completeBatch();
        if (this._batch.updates && this._batch.updates.length) {
          newUpdates.push(this._batch);
        }
        this._batch = this._startBatch(update);
      }
      this._updateItems[reviewerId] = {
        reviewer: update.reviewer,
        state: update.state,
      };
      if (this._lastState[reviewerId]) {
        this._updateItems[reviewerId].prev_state = this._lastState[reviewerId];
      }
      return newUpdates;
    }.bind(this), []);
    this._completeBatch();
    if (this._batch.updates && this._batch.updates.length) {
      newUpdates.push(this._batch);
    }
    this.result.reviewer_updates = newUpdates;
  };

  /**
   * Generates update message for reviewer state change.
   * @param {string} prev previous reviewer state.
   * @param {string} state current reviewer state.
   * @return {string}
   */
  GrReviewerUpdatesParser.prototype._getUpdateMessage = function(prev, state) {
    if (prev === 'REMOVED' || !prev) {
      return 'added to ' + state + ': ';
    } else if (state === 'REMOVED') {
      if (prev) {
        return 'removed from ' + prev + ': ';
      } else {
        return 'removed : ';
      }
    } else {
      return 'moved from ' + prev + ' to ' + state + ': ';
    }
  };

  /**
   * Groups updates for same category (eg CC->CC) into a hash arrays of
   * reviewers.
   * @param {!Array<!Object>} updates Array of ReviewerUpdateItemInfo.
   * @return {!Object} Hash of arrays of AccountInfo, message as key.
   */
  GrReviewerUpdatesParser.prototype._groupUpdatesByMessage = function(updates) {
    return updates.reduce(function(result, item) {
      var message = this._getUpdateMessage(item.prev_state, item.state);
      if (!result[message]) {
        result[message] = [];
      }
      result[message].push(item.reviewer);
      return result;
    }.bind(this), {});
  };

  /**
   * Generates text messages for grouped reviewer updates.
   * Formats reviewer updates to a (not yet implemented) EventInfo instance.
   * @see https://gerrit-review.googlesource.com/c/94490/
   */
  GrReviewerUpdatesParser.prototype._formatUpdates = function() {
    this.result.reviewer_updates.forEach(function(update) {
      var grouppedReviewers = this._groupUpdatesByMessage(update.updates);
      var newUpdates = [];
      for (var message in grouppedReviewers) {
        if (grouppedReviewers.hasOwnProperty(message)) {
          newUpdates.push({
            message: message,
            reviewers: grouppedReviewers[message],
          });
        }
      }
      update.updates = newUpdates;
    }.bind(this));
  };

  window.GrReviewerUpdatesParser = GrReviewerUpdatesParser;

})(window);
