// Copyright (C) 2008 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.rpc;

import com.google.gerrit.client.changes.ChangeListService;
import com.google.gerrit.client.changes.ToggleStarRequest;
import com.google.gerrit.client.data.AccountDashboardInfo;
import com.google.gerrit.client.data.ChangeInfo;
import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.ChangeAccess;
import com.google.gerrit.client.reviewdb.PatchSetApproval;
import com.google.gerrit.client.reviewdb.PatchLineComment;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.client.reviewdb.RevId;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.StarredChange;
import com.google.gerrit.client.rpc.NoSuchEntityException;
import com.google.gerrit.server.BaseServiceImplementation;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.client.VoidResult;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.gwtorm.client.Transaction;
import com.google.gwtorm.client.impl.ListResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ChangeListServiceImpl extends BaseServiceImplementation implements
    ChangeListService {
  private static final Comparator<ChangeInfo> ID_COMP =
      new Comparator<ChangeInfo>() {
        public int compare(final ChangeInfo o1, final ChangeInfo o2) {
          return o1.getId().get() - o2.getId().get();
        }
      };
  private static final Comparator<ChangeInfo> SORT_KEY_COMP =
      new Comparator<ChangeInfo>() {
        public int compare(final ChangeInfo o1, final ChangeInfo o2) {
          return o2.getSortKey().compareTo(o1.getSortKey());
        }
      };
  private static final Comparator<Change> QUERY_PREV =
      new Comparator<Change>() {
        public int compare(final Change a, final Change b) {
          return a.getSortKey().compareTo(b.getSortKey());
        }
      };
  private static final Comparator<Change> QUERY_NEXT =
      new Comparator<Change>() {
        public int compare(final Change a, final Change b) {
          return b.getSortKey().compareTo(a.getSortKey());
        }
      };

  private static final int MAX_PER_PAGE = 100;

  private static int safePageSize(final int pageSize) {
    return 0 < pageSize && pageSize <= MAX_PER_PAGE ? pageSize : MAX_PER_PAGE;
  }

  private final Provider<CurrentUser> currentUser;
  private final ChangeControl.Factory changeControlFactory;
  private final AccountInfoCacheFactory.Factory accountInfoCacheFactory;

  @Inject
  ChangeListServiceImpl(final Provider<ReviewDb> schema,
      final Provider<CurrentUser> currentUser,
      final ChangeControl.Factory changeControlFactory,
      final AccountInfoCacheFactory.Factory accountInfoCacheFactory) {
    super(schema, currentUser);
    this.currentUser = currentUser;
    this.changeControlFactory = changeControlFactory;
    this.accountInfoCacheFactory = accountInfoCacheFactory;
  }

  private boolean canRead(final Change c) {
    try {
      return changeControlFactory.controlFor(c).isVisible();
    } catch (NoSuchChangeException e) {
      return false;
    }
  }

  public void allOpenPrev(final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryPrev(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().allOpenPrev(sortKey, slim);
      }
    });
  }

  public void allOpenNext(final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryNext(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().allOpenNext(sortKey, slim);
      }
    });
  }

  public void byProjectOpenPrev(final Project.NameKey project,
      final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryPrev(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().byProjectOpenPrev(project, sortKey, slim);
      }
    });
  }

  public void byProjectOpenNext(final Project.NameKey project,
      final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryNext(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().byProjectOpenNext(project, sortKey, slim);
      }
    });
  }

  public void byProjectClosedPrev(final Project.NameKey project,
      final Change.Status s, final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryPrev(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().byProjectClosedPrev(s.getCode(), project, sortKey,
            slim);
      }
    });
  }

  public void byProjectClosedNext(final Project.NameKey project,
      final Change.Status s, final String pos, final int pageSize,
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryNext(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
          throws OrmException {
        return db.changes().byProjectClosedNext(s.getCode(), project, sortKey,
            slim);
      }
    });
  }

  public void allClosedPrev(final Change.Status s, final String pos,
      final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryPrev(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int lim, String key)
          throws OrmException {
        return db.changes().allClosedPrev(s.getCode(), key, lim);
      }
    });
  }

  public void allClosedNext(final Change.Status s, final String pos,
      final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryNext(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int lim, String key)
          throws OrmException {
        return db.changes().allClosedNext(s.getCode(), key, lim);
      }
    });
  }

  @Override
  public void allQueryPrev(final String query, final String pos,
      final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryPrev(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int lim, String key)
          throws OrmException {
        return searchQuery(db, query, lim, key, QUERY_PREV);
      }
    });
  }

  @Override
  public void allQueryNext(final String query, final String pos,
      final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new QueryNext(pageSize, pos) {
      @Override
      ResultSet<Change> query(ReviewDb db, int lim, String key)
          throws OrmException {
        return searchQuery(db, query, lim, key, QUERY_NEXT);
      }
    });
  }

  private ResultSet<Change> searchQuery(final ReviewDb db, String query,
      final int limit, final String key, final Comparator<Change> cmp)
      throws OrmException {
    List<Change> result = new ArrayList<Change>();
    final HashSet<Change.Id> want = new HashSet<Change.Id>();
    query = query.trim();

    if (query.matches("^[1-9][0-9]*$")) {
      want.add(Change.Id.parse(query));

    } else if (query.matches("^[iI][0-9a-f]{4,}.*$")) {
      if (query.startsWith("i")) {
        query = "I" + query.substring(1);
      }
      final Change.Key a = new Change.Key(query);
      final Change.Key b = a.max();
      filterBySortKey(result, db.changes().byKeyRange(a, b), cmp, key);
      Collections.sort(result, cmp);
      if (limit < result.size()) {
        result = result.subList(0, limit);
      }

    } else if (query.matches("^([0-9a-fA-F]{4," + RevId.LEN + "})$")) {
      final RevId id = new RevId(query);
      final ResultSet<PatchSet> patches;
      if (id.isComplete()) {
        patches = db.patchSets().byRevision(id);
      } else {
        patches = db.patchSets().byRevisionRange(id, id.max());
      }
      for (PatchSet p : patches) {
        want.add(p.getId().getParentKey());
      }
    } else if (query.contains("owner:")) {
      String[] parsedQuery = query.split(":");
      if (parsedQuery.length > 1) {
        filterBySortKey(result, changesCreatedBy(db, parsedQuery[1]), cmp, key);
      }
    } else if (query.contains("reviewer:")) {
      String[] parsedQuery = query.split(":");
      if (parsedQuery.length > 1) {
        want.addAll(changesReviewedBy(db, parsedQuery[1]));
      }
    }

    if (result.isEmpty() && want.isEmpty()) {
      return new ListResultSet<Change>(Collections.<Change> emptyList());
    }

    filterBySortKey(result, db.changes().get(want), cmp, key);
    Collections.sort(result, cmp);
    if (limit < result.size()) {
      result = result.subList(0, limit);
    }
    return new ListResultSet<Change>(result);
  }

  private static void filterBySortKey(final List<Change> dst,
      final Iterable<Change> src, final Comparator<Change> cmp, final String key) {
    if (cmp == QUERY_PREV) {
      for (Change c : src) {
        if (c.getSortKey().compareTo(key) > 0) {
          dst.add(c);
        }
      }
    } else /* cmp == QUERY_NEXT */{
      for (Change c : src) {
        if (c.getSortKey().compareTo(key) < 0) {
          dst.add(c);
        }
      }
    }
  }

  public void forAccount(final Account.Id id,
      final AsyncCallback<AccountDashboardInfo> callback) {
    final Account.Id me = getAccountId();
    final Account.Id target = id != null ? id : me;
    if (target == null) {
      callback.onFailure(new NoSuchEntityException());
      return;
    }

    run(callback, new Action<AccountDashboardInfo>() {
      public AccountDashboardInfo run(final ReviewDb db) throws OrmException,
          Failure {
        final AccountInfoCacheFactory ac = accountInfoCacheFactory.create();
        final Account user = ac.get(target);
        if (user == null) {
          throw new Failure(new NoSuchEntityException());
        }

        final Set<Change.Id> stars = currentUser.get().getStarredChanges();
        final ChangeAccess changes = db.changes();
        final AccountDashboardInfo d;

        final Set<Change.Id> openReviews = new HashSet<Change.Id>();
        final Set<Change.Id> closedReviews = new HashSet<Change.Id>();
        for (final PatchSetApproval ca : db.patchSetApprovals().openByUser(id)) {
          openReviews.add(ca.getPatchSetId().getParentKey());
        }
        for (final PatchSetApproval ca : db.patchSetApprovals()
            .closedByUser(id)) {
          closedReviews.add(ca.getPatchSetId().getParentKey());
        }

        d = new AccountDashboardInfo(target);
        d.setByOwner(filter(changes.byOwnerOpen(target), stars, ac));
        d.setClosed(filter(changes.byOwnerClosed(target), stars, ac));

        for (final ChangeInfo c : d.getByOwner()) {
          openReviews.remove(c.getId());
        }
        d.setForReview(filter(changes.get(openReviews), stars, ac));
        Collections.sort(d.getForReview(), ID_COMP);

        for (final ChangeInfo c : d.getClosed()) {
          closedReviews.remove(c.getId());
        }
        if (!closedReviews.isEmpty()) {
          d.getClosed().addAll(filter(changes.get(closedReviews), stars, ac));
          Collections.sort(d.getClosed(), SORT_KEY_COMP);
        }

        d.setAccounts(ac.create());
        return d;
      }
    });
  }

  public void myStarredChanges(
      final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new Action<SingleListChangeInfo>() {
      public SingleListChangeInfo run(final ReviewDb db) throws OrmException {
        final Account.Id me = getAccountId();
        final AccountInfoCacheFactory ac = accountInfoCacheFactory.create();
        final SingleListChangeInfo d = new SingleListChangeInfo();
        final Set<Change.Id> starred = currentUser.get().getStarredChanges();
        d.setChanges(filter(db.changes().get(starred), starred, ac));
        Collections.sort(d.getChanges(), new Comparator<ChangeInfo>() {
          public int compare(final ChangeInfo o1, final ChangeInfo o2) {
            return o1.getLastUpdatedOn().compareTo(o2.getLastUpdatedOn());
          }
        });
        d.setAccounts(ac.create());
        return d;
      }
    });
  }

  public void myDraftChanges(final AsyncCallback<SingleListChangeInfo> callback) {
    run(callback, new Action<SingleListChangeInfo>() {
      public SingleListChangeInfo run(final ReviewDb db) throws OrmException {
        final Account.Id me = getAccountId();
        final AccountInfoCacheFactory ac = accountInfoCacheFactory.create();
        final SingleListChangeInfo d = new SingleListChangeInfo();
        final Set<Change.Id> starred = currentUser.get().getStarredChanges();
        final Set<Change.Id> drafted = draftedBy(db, me);
        d.setChanges(filter(db.changes().get(drafted), starred, ac));
        Collections.sort(d.getChanges(), new Comparator<ChangeInfo>() {
          public int compare(final ChangeInfo o1, final ChangeInfo o2) {
            return o1.getLastUpdatedOn().compareTo(o2.getLastUpdatedOn());
          }
        });
        d.setAccounts(ac.create());
        return d;
      }
    });
  }

  public void toggleStars(final ToggleStarRequest req,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException {
        final Account.Id me = getAccountId();
        final Set<Change.Id> existing = currentUser.get().getStarredChanges();
        final ArrayList<StarredChange> add = new ArrayList<StarredChange>();
        final ArrayList<StarredChange> remove = new ArrayList<StarredChange>();

        if (req.getAddSet() != null) {
          for (final Change.Id id : req.getAddSet()) {
            if (!existing.contains(id)) {
              add.add(new StarredChange(new StarredChange.Key(me, id)));
            }
          }
        }

        if (req.getRemoveSet() != null) {
          for (final Change.Id id : req.getRemoveSet()) {
            if (existing.contains(id)) {
              remove.add(new StarredChange(new StarredChange.Key(me, id)));
            }
          }
        }

        if (!add.isEmpty() || !remove.isEmpty()) {
          final Transaction txn = db.beginTransaction();
          db.starredChanges().insert(add);
          db.starredChanges().delete(remove);
          txn.commit();
        }
        return VoidResult.INSTANCE;
      }
    });
  }

  public void myStarredChangeIds(final AsyncCallback<Set<Change.Id>> callback) {
    callback.onSuccess(currentUser.get().getStarredChanges());
  }

  private List<ChangeInfo> filter(final ResultSet<Change> rs,
      final Set<Change.Id> starred, final AccountInfoCacheFactory accts) {
    final ArrayList<ChangeInfo> r = new ArrayList<ChangeInfo>();
    for (final Change c : rs) {
      if (canRead(c)) {
        final ChangeInfo ci = new ChangeInfo(c);
        accts.want(ci.getOwner());
        ci.setStarred(starred.contains(ci.getId()));
        r.add(ci);
      }
    }
    return r;
  }

  private static Set<Change.Id> draftedBy(final ReviewDb db, final Account.Id me)
      throws OrmException {
    final Set<Change.Id> existing = new HashSet<Change.Id>();
    if (me != null) {
      for (final PatchLineComment sc : db.patchComments().draftByAuthor(me)) {
        final Change.Id c =
            sc.getKey().getParentKey().getParentKey().getParentKey();
        existing.add(c);
      }
    }
    return existing;
  }

  /**
   * @return a set of all the account ID's matching the given user name in
   *         either of the following columns: ssh name, email address, full name
   */
  private static Set<Account.Id> getAccountSources(final ReviewDb db,
      final String userName) throws OrmException {
    Set<Account.Id> result = new HashSet<Account.Id>();
    String a = userName;
    String b = userName + "\u9fa5";
    addAll(result, db.accounts().suggestBySshUserName(a, b, 10));
    addAll(result, db.accounts().suggestByFullName(a, b, 10));
    for (AccountExternalId extId : db.accountExternalIds()
        .suggestByEmailAddress(a, b, 10)) {
      result.add(extId.getAccountId());
    }
    return result;
  }

  private static void addAll(Set<Account.Id> result, ResultSet<Account> rs) {
    for (Account account : rs) {
      result.add(account.getId());
    }
  }

  /**
   * @return a set of all the changes created by userName. This method tries to
   *         find userName in 1) the ssh user names, 2) the full names and 3)
   *         the email addresses. The returned changes are unique and sorted by
   *         time stamp, newer first.
   */
  private List<Change> changesCreatedBy(final ReviewDb db, final String userName)
      throws OrmException {
    final List<Change> resultChanges = new ArrayList<Change>();
    for (Account.Id account : getAccountSources(db, userName)) {
      for (Change change : db.changes().byOwnerOpen(account)) {
        resultChanges.add(change);
      }
      for (Change change : db.changes().byOwnerClosedAll(account)) {
        resultChanges.add(change);
      }
    }
    return resultChanges;
  }

  /**
   * @return a set of all the changes reviewed by userName. This method tries to
   *         find userName in 1) the ssh user names, 2) the full names and the
   *         email addresses. The returned changes are unique and sorted by time
   *         stamp, newer first.
   */
  private Set<Change.Id> changesReviewedBy(final ReviewDb db,
      final String userName) throws OrmException {
    final Set<Change.Id> resultChanges = new HashSet<Change.Id>();
    for (Account.Id account : getAccountSources(db, userName)) {
      for (PatchSetApproval a : db.patchSetApprovals().openByUser(account)) {
        resultChanges.add(a.getPatchSetId().getParentKey());
      }
      for (PatchSetApproval a : db.patchSetApprovals().closedByUserAll(account)) {
        resultChanges.add(a.getPatchSetId().getParentKey());
      }
    }
    return resultChanges;
  }

  private abstract class QueryNext implements Action<SingleListChangeInfo> {
    protected final String pos;
    protected final int limit;
    protected final int slim;

    QueryNext(final int pageSize, final String pos) {
      this.pos = pos;
      this.limit = safePageSize(pageSize);
      this.slim = limit + 1;
    }

    public SingleListChangeInfo run(final ReviewDb db) throws OrmException {
      final Account.Id me = getAccountId();
      final AccountInfoCacheFactory ac = accountInfoCacheFactory.create();
      final SingleListChangeInfo d = new SingleListChangeInfo();
      final Set<Change.Id> starred = currentUser.get().getStarredChanges();

      boolean results = true;
      String sortKey = pos;
      final ArrayList<ChangeInfo> list = new ArrayList<ChangeInfo>();
      while (results && list.size() < slim) {
        results = false;
        final ResultSet<Change> rs = query(db, slim, sortKey);
        for (final Change c : rs) {
          results = true;
          if (canRead(c)) {
            final ChangeInfo ci = new ChangeInfo(c);
            ac.want(ci.getOwner());
            ci.setStarred(starred.contains(ci.getId()));
            list.add(ci);
            if (list.size() == slim) {
              rs.close();
              break;
            }
          }
          sortKey = c.getSortKey();
        }
      }

      final boolean atEnd = finish(list);
      d.setChanges(list, atEnd);
      d.setAccounts(ac.create());
      return d;
    }

    boolean finish(final ArrayList<ChangeInfo> list) {
      final boolean atEnd = list.size() <= limit;
      if (list.size() == slim) {
        list.remove(limit);
      }
      return atEnd;
    }

    abstract ResultSet<Change> query(final ReviewDb db, final int slim,
        String sortKey) throws OrmException;
  }

  private abstract class QueryPrev extends QueryNext {
    QueryPrev(int pageSize, String pos) {
      super(pageSize, pos);
    }

    @Override
    boolean finish(final ArrayList<ChangeInfo> list) {
      final boolean atEnd = super.finish(list);
      Collections.reverse(list);
      return atEnd;
    }
  }
}
