// Copyright (C) 2015 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.

package com.google.gerrit.server.change;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.change.HashtagsUtil.extractTags;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.changes.HashtagsInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.change.HashtagsUtil.InvalidHashtagException;
import com.google.gerrit.server.extensions.events.HashtagsEdited;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
import com.google.gerrit.server.validators.HashtagValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class SetHashtagsOp implements BatchUpdateOp {
  public interface Factory {
    SetHashtagsOp create(HashtagsInput input);
  }

  private final NotesMigration notesMigration;
  private final ChangeMessagesUtil cmUtil;
  private final PluginSetContext<HashtagValidationListener> validationListeners;
  private final HashtagsEdited hashtagsEdited;
  private final HashtagsInput input;

  private boolean fireEvent = true;

  private Change change;
  private Set<String> toAdd;
  private Set<String> toRemove;
  private ImmutableSortedSet<String> updatedHashtags;

  @Inject
  SetHashtagsOp(
      NotesMigration notesMigration,
      ChangeMessagesUtil cmUtil,
      PluginSetContext<HashtagValidationListener> validationListeners,
      HashtagsEdited hashtagsEdited,
      @Assisted @Nullable HashtagsInput input) {
    this.notesMigration = notesMigration;
    this.cmUtil = cmUtil;
    this.validationListeners = validationListeners;
    this.hashtagsEdited = hashtagsEdited;
    this.input = input;
  }

  public SetHashtagsOp setFireEvent(boolean fireEvent) {
    this.fireEvent = fireEvent;
    return this;
  }

  @Override
  public boolean updateChange(ChangeContext ctx)
      throws AuthException, BadRequestException, MethodNotAllowedException, OrmException,
          IOException {
    if (!notesMigration.readChanges()) {
      throw new MethodNotAllowedException("Cannot add hashtags; NoteDb is disabled");
    }
    if (input == null || (input.add == null && input.remove == null)) {
      updatedHashtags = ImmutableSortedSet.of();
      return false;
    }

    change = ctx.getChange();
    ChangeUpdate update = ctx.getUpdate(change.currentPatchSetId());
    ChangeNotes notes = update.getNotes().load();

    try {
      Set<String> existingHashtags = notes.getHashtags();
      Set<String> updated = new HashSet<>();
      toAdd = new HashSet<>(extractTags(input.add));
      toRemove = new HashSet<>(extractTags(input.remove));

      validationListeners.runEach(
          l -> l.validateHashtags(update.getChange(), toAdd, toRemove), ValidationException.class);
      updated.addAll(existingHashtags);
      toAdd.removeAll(existingHashtags);
      toRemove.retainAll(existingHashtags);
      if (updated()) {
        updated.addAll(toAdd);
        updated.removeAll(toRemove);
        update.setHashtags(updated);
        addMessage(ctx, update);
      }

      updatedHashtags = ImmutableSortedSet.copyOf(updated);
      return true;
    } catch (ValidationException | InvalidHashtagException e) {
      throw new BadRequestException(e.getMessage(), e);
    }
  }

  private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
    StringBuilder msg = new StringBuilder();
    appendHashtagMessage(msg, "added", toAdd);
    appendHashtagMessage(msg, "removed", toRemove);
    ChangeMessage cmsg =
        ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_SET_HASHTAGS);
    cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
  }

  private void appendHashtagMessage(StringBuilder b, String action, Set<String> hashtags) {
    if (isNullOrEmpty(hashtags)) {
      return;
    }

    if (b.length() > 0) {
      b.append("\n");
    }
    b.append("Hashtag");
    if (hashtags.size() > 1) {
      b.append("s");
    }
    b.append(" ");
    b.append(action);
    b.append(": ");
    b.append(Joiner.on(", ").join(Ordering.natural().sortedCopy(hashtags)));
  }

  @Override
  public void postUpdate(Context ctx) throws OrmException {
    if (updated() && fireEvent) {
      hashtagsEdited.fire(
          change, ctx.getAccount(), updatedHashtags, toAdd, toRemove, ctx.getWhen());
    }
  }

  public ImmutableSortedSet<String> getUpdatedHashtags() {
    checkState(updatedHashtags != null, "getUpdatedHashtags() only valid after executing op");
    return updatedHashtags;
  }

  private boolean updated() {
    return !isNullOrEmpty(toAdd) || !isNullOrEmpty(toRemove);
  }

  private static boolean isNullOrEmpty(Collection<?> coll) {
    return coll == null || coll.isEmpty();
  }
}
