// Copyright (C) 2013 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.googlesource.gerrit.plugins.its.base.util;

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.data.ApprovalAttribute;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gerrit.server.data.PatchSetAttribute;
import com.google.gerrit.server.data.RefUpdateAttribute;
import com.google.gerrit.server.events.ChangeAbandonedEvent;
import com.google.gerrit.server.events.ChangeEvent;
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.PatchSetEvent;
import com.google.gerrit.server.events.PrivateStateChangedEvent;
import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.events.WorkInProgressStateChangedEvent;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.workflow.RefEventProperties;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;

/** Extractor to translate an {@link ChangeEvent} to a map of properties}. */
public class PropertyExtractor {
  private final ItsProjectExtractor itsProjectExtractor;
  private final IssueExtractor issueExtractor;
  private final PropertyAttributeExtractor propertyAttributeExtractor;
  private final String pluginName;

  @Inject
  PropertyExtractor(
      IssueExtractor issueExtractor,
      ItsProjectExtractor itsProjectExtractor,
      PropertyAttributeExtractor propertyAttributeExtractor,
      @PluginName String pluginName) {
    this.issueExtractor = issueExtractor;
    this.itsProjectExtractor = itsProjectExtractor;
    this.propertyAttributeExtractor = propertyAttributeExtractor;
    this.pluginName = pluginName;
  }

  /**
   * creates a patch id for change id string and patchset id string.
   *
   * @param changeId String representation of the patch sets {@code Change.Id@}
   * @param patchId String representation of the patch sets {@code Patchset.Id@}
   * @return PatchSet.Id for the specified patch set. If the String to int conversion fails for any
   *     of the parameters, null is returned.
   */
  private PatchSet.Id newPatchSetId(String changeId, String patchId) {
    try {
      return new PatchSet.Id(new Change.Id(Integer.parseInt(changeId)), Integer.parseInt(patchId));
    } catch (NumberFormatException e) {
      return null;
    }
  }

  private Map<String, Set<String>> extractMapFrom(PatchSetEvent event, Map<String, String> common) {
    ChangeAttribute change = event.change.get();
    PatchSetAttribute patchSet = event.patchSet.get();
    common.putAll(propertyAttributeExtractor.extractFrom(change));
    common.putAll(propertyAttributeExtractor.extractFrom(patchSet));
    PatchSet.Id patchSetId =
        newPatchSetId(Integer.toString(change.number), Integer.toString(patchSet.number));
    return issueExtractor.getIssueIds(change.project, patchSet.revision, patchSetId);
  }

  private Map<String, Set<String>> extractFrom(
      ChangeAbandonedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.abandoner.get(), "abandoner"));
    common.put("reason", event.reason);
    return extractMapFrom(event, common);
  }

  private Map<String, Set<String>> extractFrom(
      ChangeMergedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.submitter.get(), "submitter"));
    return extractMapFrom(event, common);
  }

  private Map<String, Set<String>> extractFrom(
      ChangeRestoredEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.restorer.get(), "restorer"));
    common.put("reason", event.reason);
    return extractMapFrom(event, common);
  }

  private Map<String, Set<String>> extractFrom(RefUpdatedEvent event, Map<String, String> common) {
    if (event.submitter != null) {
      common.putAll(propertyAttributeExtractor.extractFrom(event.submitter.get(), "submitter"));
    }
    common.putAll(propertyAttributeExtractor.extractFrom(event.refUpdate.get()));
    RefUpdateAttribute refUpdateEvent = event.refUpdate.get();
    String commitId =
        (refUpdateEvent.newRev.equals(ObjectId.zeroId().name())
            ? refUpdateEvent.oldRev
            : refUpdateEvent.newRev);
    return issueExtractor.getIssueIds(event.getProjectNameKey().get(), commitId);
  }

  private Map<String, Set<String>> extractFrom(
      PatchSetCreatedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.uploader.get(), "uploader"));
    return extractMapFrom(event, common);
  }

  private Map<String, Set<String>> extractFrom(
      CommentAddedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.author.get(), "commenter"));
    common.put("comment", event.comment);
    if (event.approvals != null) {
      for (ApprovalAttribute approvalAttribute : event.approvals.get()) {
        common.putAll(propertyAttributeExtractor.extractFrom(approvalAttribute));
      }
    }
    return extractMapFrom(event, common);
  }

  private Map<String, Set<String>> extractFrom(
      WorkInProgressStateChangedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.changer.get(), "changer"));
    return extractFrom((ChangeEvent) event, common);
  }

  private Map<String, Set<String>> extractFrom(
      PrivateStateChangedEvent event, Map<String, String> common) {
    common.putAll(propertyAttributeExtractor.extractFrom(event.changer.get(), "changer"));
    return extractFrom((ChangeEvent) event, common);
  }

  private Map<String, Set<String>> extractFrom(ChangeEvent event, Map<String, String> common) {
    common.put("event-type", event.type);
    ChangeAttribute change = event.change.get();
    common.putAll(propertyAttributeExtractor.extractFrom(change));
    common.put("refName", event.refName);

    // Got no patch set information, extract from commit message.
    return issueExtractor.getIssueIdsFromCommitMessage(change.commitMessage);
  }

  /**
   * A set of properties extracted from an event.
   *
   * <p>As events may relate to more that a single issue and a group of properties should be tied to
   * a single issue, we need to return {@code Set<Map>} of properties. As properties we understand a
   * map of event attributes. Using this approach, a PatchSetCreatedEvent for a patch set with
   * commit message:
   *
   * <pre>
   *   (bug 4711) Fix treatment of special characters in title
   *
   *   This commit mitigates the effects of bug 42, but does not fix them.
   *
   *   Change-Id: I1234567891123456789212345678931234567894
   * </pre>
   *
   * may return both
   *
   * <pre>
   *   issue: 4711
   *   association: subject
   *   event: patchset-created
   * </pre>
   *
   * and
   *
   * <pre>
   *   issue: 42
   *   association: body
   *   event: patchset-created
   * </pre>
   *
   * Thereby, sites can choose to cause different actions for different issues associated to the
   * same event. So in the above example, a comment "mentioned in change 123" may be added for issue
   * 42, and a comment "fixed by change 123” may be added for issue 4711.
   *
   * @param event The event to extract property maps from.
   * @return set of property maps extracted from the event.
   */
  public RefEventProperties extractFrom(RefEvent event) {
    Map<String, Set<String>> associations = null;
    Map<String, String> common = new HashMap<>();
    common.put("event", event.getClass().getName());
    String project = event.getProjectNameKey().get();
    common.put("event-type", event.type);
    common.put("project", project);

    itsProjectExtractor
        .getItsProject(project)
        .ifPresent(itsProject -> common.put("its-project", itsProject));
    common.put("ref", event.getRefName());
    common.put("itsName", pluginName);

    if (event instanceof ChangeAbandonedEvent) {
      associations = extractFrom((ChangeAbandonedEvent) event, common);
    } else if (event instanceof ChangeMergedEvent) {
      associations = extractFrom((ChangeMergedEvent) event, common);
    } else if (event instanceof ChangeRestoredEvent) {
      associations = extractFrom((ChangeRestoredEvent) event, common);
    } else if (event instanceof CommentAddedEvent) {
      associations = extractFrom((CommentAddedEvent) event, common);
    } else if (event instanceof PatchSetCreatedEvent) {
      associations = extractFrom((PatchSetCreatedEvent) event, common);
    } else if (event instanceof RefUpdatedEvent) {
      associations = extractFrom((RefUpdatedEvent) event, common);
    } else if (event instanceof PrivateStateChangedEvent) {
      associations = extractFrom((PrivateStateChangedEvent) event, common);
    } else if (event instanceof WorkInProgressStateChangedEvent) {
      associations = extractFrom((WorkInProgressStateChangedEvent) event, common);
    }

    Set<Map<String, String>> ret = new HashSet<>();
    if (associations != null) {
      for (Entry<String, Set<String>> assoc : associations.entrySet()) {
        Map<String, String> properties = new HashMap<>();
        properties.put("issue", assoc.getKey());
        properties.put("association", String.join(" ", assoc.getValue()));
        properties.putAll(common);
        ret.add(properties);
      }
    }
    return new RefEventProperties(common, ret);
  }
}
