// 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.common.collect.Sets;
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.DraftPublishedEvent;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.PatchSetEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.workflow.Property;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;

/** Extractor to translate an {@link ChangeEvent} to {@link Property Properties}. */
public class PropertyExtractor {
  private IssueExtractor issueExtractor;
  private Property.Factory propertyFactory;
  private PropertyAttributeExtractor propertyAttributeExtractor;
  private final String pluginName;

  @Inject
  PropertyExtractor(
      IssueExtractor issueExtractor,
      Property.Factory propertyFactory,
      PropertyAttributeExtractor propertyAttributeExtractor,
      @PluginName String pluginName) {
    this.issueExtractor = issueExtractor;
    this.propertyFactory = propertyFactory;
    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>> extractFrom(PatchSetEvent event, Set<Property> common) {
    common.add(propertyFactory.create("event-type", event.type));
    ChangeAttribute change = event.change.get();
    PatchSetAttribute patchSet = event.patchSet.get();
    common.addAll(propertyAttributeExtractor.extractFrom(change));
    common.addAll(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, Set<Property> common) {
    common.addAll(propertyAttributeExtractor.extractFrom(event.abandoner.get(), "abandoner"));
    common.add(propertyFactory.create("reason", event.reason));
    return extractFrom((PatchSetEvent) event, common);
  }

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

  private Map<String, Set<String>> extractFrom(ChangeRestoredEvent event, Set<Property> common) {
    common.addAll(propertyAttributeExtractor.extractFrom(event.restorer.get(), "restorer"));
    common.add(propertyFactory.create("reason", event.reason));
    return extractFrom((PatchSetEvent) event, common);
  }

  private Map<String, Set<String>> extractFrom(DraftPublishedEvent event, Set<Property> common) {
    common.addAll(propertyAttributeExtractor.extractFrom(event.uploader.get(), "uploader"));
    return extractFrom((PatchSetEvent) event, common);
  }

  private Map<String, Set<String>> extractFrom(RefUpdatedEvent event, Set<Property> common) {
    common.add(propertyFactory.create("event-type", event.type));
    if (event.submitter != null) {
      common.addAll(propertyAttributeExtractor.extractFrom(event.submitter.get(), "submitter"));
    }
    common.addAll(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, Set<Property> common) {
    common.addAll(propertyAttributeExtractor.extractFrom(event.uploader.get(), "uploader"));
    return extractFrom((PatchSetEvent) event, common);
  }

  private Map<String, Set<String>> extractFrom(CommentAddedEvent event, Set<Property> common) {
    common.addAll(propertyAttributeExtractor.extractFrom(event.author.get(), "commenter"));
    if (event.approvals != null) {
      for (ApprovalAttribute approvalAttribute : event.approvals.get()) {
        common.addAll(propertyAttributeExtractor.extractFrom(approvalAttribute));
      }
    }
    common.add(propertyFactory.create("comment", event.comment));
    return extractFrom((PatchSetEvent) event, common);
  }

  /**
   * A set of property sets extracted from an event.
   *
   * <p>As events may relate to more that a single issue, and properties sets are should be tied to
   * a single issue, returning {@code Set<Property>} is not sufficient, and we need to return {@code
   * Set<Set<Property>>}. 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 sets from.
   * @return sets of property sets extracted from the event.
   */
  public Set<Set<Property>> extractFrom(Event event) {
    Map<String, Set<String>> associations = null;
    Set<Set<Property>> ret = Sets.newHashSet();

    Set<Property> common = Sets.newHashSet();
    common.add(propertyFactory.create("event", event.getClass().getName()));

    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 DraftPublishedEvent) {
      associations = extractFrom((DraftPublishedEvent) event, common);
    } else if (event instanceof PatchSetCreatedEvent) {
      associations = extractFrom((PatchSetCreatedEvent) event, common);
    } else if (event instanceof RefUpdatedEvent) {
      associations = extractFrom((RefUpdatedEvent) event, common);
    }

    if (associations != null) {
      for (String issue : associations.keySet()) {
        Set<Property> properties = Sets.newHashSet();
        Property property = propertyFactory.create("issue", issue);
        properties.add(property);
        property = propertyFactory.create("its-name", pluginName);
        properties.add(property);
        for (String occurrence : associations.get(issue)) {
          property = propertyFactory.create("association", occurrence);
          properties.add(property);
        }
        properties.addAll(common);
        ret.add(properties);
      }
    }
    return ret;
  }
}
