// Copyright (C) 2016 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.reviewit.app;

import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.changes.AbandonInput;
import com.google.gerrit.extensions.api.changes.RestoreInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.reviewit.util.FormatUtil;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Change {
  private final GerritApi api;

  public ChangeInfo info;
  private Map<String, DiffInfo> diffs = new HashMap<>();
  private Integer inlineCommentCount;

  public Change(GerritApi api, ChangeInfo info) {
    this.api = api;
    this.info = info;
  }

  public void reload() throws RestApiException {
    info = api.changes().id(info._number).get();
    diffs = null;
    inlineCommentCount = null;
  }

  public RevisionInfo currentRevision() {
    return info.revisions.get(info.currentRevision);
  }

  public Collection<AccountInfo> reviewers(boolean filterOutOwner) {
    if (info.reviewers == null
        || !info.reviewers.containsKey(ReviewerState.REVIEWER)) {
      return Collections.emptySet();
    }

    Collection<AccountInfo> reviewers =
        info.reviewers.get(ReviewerState.REVIEWER);
    if (reviewers != null) {
      if (filterOutOwner) {
        return ImmutableList.copyOf(Collections2.filter(reviewers,
            new Predicate<AccountInfo>() {
          @Override
          public boolean apply(AccountInfo r) {
            return !r._accountId.equals(info.owner._accountId);
          }
        }));
      } else {
        return ImmutableList.copyOf(reviewers);
      }
    } else {
      return Collections.emptySet();
    }
  }

  public Collection<AccountInfo> ccs() {
    if (info.reviewers == null
        || !info.reviewers.containsKey(ReviewerState.CC)) {
      return Collections.emptySet();
    }

    Collection<AccountInfo> ccs = info.reviewers.get(ReviewerState.CC);
    if (ccs != null) {
      return ImmutableList.copyOf(ccs);
    } else {
      return Collections.emptySet();
    }
  }

  public Voters voters(String label) {
    Voters voters = new Voters();
    if (info.labels == null || !info.labels.containsKey(label)) {
      return voters;
    }

    List<ApprovalInfo> all = info.labels.get(label).all;
    if (all == null) {
      return voters;
    }

    for (ApprovalInfo a : all) {
      if (a.value == null) {
        continue;
      }
      if (a.value > 0) {
        voters.likers.add(a);
      } else if (a.value < 0) {
        voters.dislikers.add(a);
      }
    }
    return voters;
  }

  public int getVote(String label, AccountInfo account) {
    LabelInfo labelInfo = info.labels.get(label);
    if (labelInfo == null) {
      return 0;
    }

    if (labelInfo.all != null) {
      for (ApprovalInfo a : labelInfo.all) {
        if (a._accountId.equals(account._accountId)) {
          return a.value;
        }
      }
    }
    return 0;
  }

  public int getInlineCommentCount() throws RestApiException {
    if (inlineCommentCount != null) {
      return inlineCommentCount;
    }

    int count = 0;
    // TODO implement commentsAsList in REST API Client
    for (List<CommentInfo> commentList : api.changes().id(info._number)
        .revision(info.currentRevision).comments().values()) {
      count += commentList.size();
    }
    inlineCommentCount = count;
    return inlineCommentCount;
  }

  public DiffInfo diff(String path) throws RestApiException {
    DiffInfo diff = diffs.get(path);
    if (diff != null) {
      return diff;
    }

    diff =
        api.changes()
            .id(info._number)
            .revision(info.currentRevision)
            .file(path)
            .diffRequest()
            .withIntraline(true)
            .get();
    diffs.put(path, diff);
    return diff;
  }

  public void addReviewer(String reviewerId) throws RestApiException {
    api.changes().id(info._number).addReviewer(reviewerId);
    reload();
  }

  public void postReview(String message, Map<String, Integer> votes)
      throws RestApiException {
    ReviewInput in = new ReviewInput();
    in.message(message);
    in.drafts = ReviewInput.DraftHandling.KEEP;
    for (Map.Entry<String, Integer> e : votes.entrySet()) {
      in.label(e.getKey(), e.getValue());
    }
    api.changes().id(info._number).current().review(in);
  }

  public void submit() throws RestApiException {
    api.changes().id(info._number).current().submit();
  }

  public void abandon(String message) throws RestApiException {
    AbandonInput in = new AbandonInput();
    in.message = message;
    api.changes().id(info._number).abandon(in);
    info.status = ChangeStatus.ABANDONED;
  }

  public void restore(String message) throws RestApiException {
    RestoreInput in = new RestoreInput();
    in.message = message;
    api.changes().id(info._number).restore(in);
    info.status = ChangeStatus.NEW;
  }

  public static class Voters {
    public Set<AccountInfo> likers = new HashSet<>();
    public Set<AccountInfo> dislikers = new HashSet<>();
  }

  public String getUrl(String serverUrl) {
    return FormatUtil.ensureSlash(serverUrl) + "#/c/" + info._number;
  }
}
