// Copyright (C) 2010 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.query.change;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gerrit.server.data.PatchSetAttribute;
import com.google.gerrit.server.data.QueryStatsAttribute;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.util.TimeUtil;
import com.google.gson.Gson;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.util.io.DisabledOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class QueryProcessor {
  private static final Logger log =
      LoggerFactory.getLogger(QueryProcessor.class);

  private final Comparator<ChangeData> cmpAfter =
      new Comparator<ChangeData>() {
        @Override
        public int compare(ChangeData a, ChangeData b) {
          try {
            return a.change().getSortKey().compareTo(b.change().getSortKey());
          } catch (OrmException e) {
            return 0;
          }
        }
      };

  private final Comparator<ChangeData> cmpBefore =
      new Comparator<ChangeData>() {
        @Override
        public int compare(ChangeData a, ChangeData b) {
          try {
            return b.change().getSortKey().compareTo(a.change().getSortKey());
          } catch (OrmException e) {
            return 0;
          }
        }
      };

  public static enum OutputFormat {
    TEXT, JSON
  }

  private final Gson gson = new Gson();
  private final SimpleDateFormat sdf =
      new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");

  private final EventFactory eventFactory;
  private final ChangeQueryBuilder queryBuilder;
  private final ChangeQueryRewriter queryRewriter;
  private final Provider<ReviewDb> db;
  private final TrackingFooters trackingFooters;
  private final CurrentUser user;
  private final int maxLimit;

  private OutputFormat outputFormat = OutputFormat.TEXT;
  private int limit;
  private int start;
  private String sortkeyAfter;
  private String sortkeyBefore;
  private boolean includePatchSets;
  private boolean includeCurrentPatchSet;
  private boolean includeApprovals;
  private boolean includeComments;
  private boolean includeFiles;
  private boolean includeCommitMessage;
  private boolean includeDependencies;
  private boolean includeSubmitRecords;
  private boolean includeAllReviewers;

  private OutputStream outputStream = DisabledOutputStream.INSTANCE;
  private PrintWriter out;
  private boolean moreResults;

  @Inject
  QueryProcessor(EventFactory eventFactory,
      ChangeQueryBuilder.Factory queryBuilder, CurrentUser currentUser,
      ChangeQueryRewriter queryRewriter, Provider<ReviewDb> db,
      TrackingFooters trackingFooters) {
    this.eventFactory = eventFactory;
    this.queryBuilder = queryBuilder.create(currentUser);
    this.queryRewriter = queryRewriter;
    this.db = db;
    this.trackingFooters = trackingFooters;
    this.user = currentUser;
    this.maxLimit = currentUser.getCapabilities()
      .getRange(GlobalCapability.QUERY_LIMIT)
      .getMax();
    this.moreResults = false;
  }

  int getLimit() {
    return limit;
  }

  void setLimit(int n) {
    limit = n;
  }

  public void setStart(int n) {
    start = n;
  }

  void setSortkeyAfter(String sortkey) {
    sortkeyAfter = sortkey;
  }

  void setSortkeyBefore(String sortkey) {
    sortkeyBefore = sortkey;
  }

  public void setIncludePatchSets(boolean on) {
    includePatchSets = on;
  }

  public boolean getIncludePatchSets() {
    return includePatchSets;
  }

  public void setIncludeCurrentPatchSet(boolean on) {
    includeCurrentPatchSet = on;
  }

  public boolean getIncludeCurrentPatchSet() {
    return includeCurrentPatchSet;
  }

  public void setIncludeApprovals(boolean on) {
    includeApprovals = on;
  }

  public void setIncludeComments(boolean on) {
    includeComments = on;
  }

  public void setIncludeFiles(boolean on) {
    includeFiles = on;
  }

  public boolean getIncludeFiles() {
    return includeFiles;
  }

  public void setIncludeDependencies(boolean on) {
    includeDependencies = on;
  }

  public boolean getIncludeDependencies() {
    return includeDependencies;
  }

  public void setIncludeCommitMessage(boolean on) {
    includeCommitMessage = on;
  }

  public void setIncludeSubmitRecords(boolean on) {
    includeSubmitRecords = on;
  }

  public void setIncludeAllReviewers(boolean on) {
    includeAllReviewers = on;
  }

  public void setOutput(OutputStream out, OutputFormat fmt) {
    this.outputStream = out;
    this.outputFormat = fmt;
  }

  /**
   * Query for changes that match the query string.
   * <p>
   * If a limit was specified using {@link #setLimit(int)} this method may
   * return up to {@code limit + 1} results, allowing the caller to determine if
   * there are more than {@code limit} matches and suggest to its own caller
   * that the query could be retried with {@link #setSortkeyBefore(String)}.
   */
  public List<ChangeData> queryChanges(String queryString)
      throws OrmException, QueryParseException {
    return queryChanges(ImmutableList.of(queryString)).get(0);
  }

  /**
   * Query for changes that match the query string.
   * <p>
   * If a limit was specified using {@link #setLimit(int)} this method may
   * return up to {@code limit + 1} results, allowing the caller to determine if
   * there are more than {@code limit} matches and suggest to its own caller
   * that the query could be retried with {@link #setSortkeyBefore(String)}.
   */
  public List<List<ChangeData>> queryChanges(List<String> queries)
      throws OrmException, QueryParseException {
    final Predicate<ChangeData> visibleToMe = queryBuilder.is_visible();
    int cnt = queries.size();

    // Parse and rewrite all queries.
    List<Integer> limits = Lists.newArrayListWithCapacity(cnt);
    List<ChangeDataSource> sources = Lists.newArrayListWithCapacity(cnt);
    for (String query : queries) {
      Predicate<ChangeData> q = parseQuery(query, visibleToMe);
      Predicate<ChangeData> s = queryRewriter.rewrite(q, start);
      if (!(s instanceof ChangeDataSource)) {
        q = Predicate.and(queryBuilder.status_open(), q);
        s = queryRewriter.rewrite(q, start);
      }
      if (!(s instanceof ChangeDataSource)) {
        throw new QueryParseException("invalid query: " + s);
      }

      // Don't trust QueryRewriter to have left the visible predicate.
      AndSource a = new AndSource(ImmutableList.of(s, visibleToMe), start);
      limits.add(limit(q));
      sources.add(a);
    }

    // Run each query asynchronously, if supported.
    List<ResultSet<ChangeData>> matches = Lists.newArrayListWithCapacity(cnt);
    for (ChangeDataSource s : sources) {
      matches.add(s.read());
    }

    List<List<ChangeData>> out = Lists.newArrayListWithCapacity(cnt);
    for (int i = 0; i < cnt; i++) {
      List<ChangeData> results = matches.get(i).toList();
      if (sortkeyAfter != null) {
        Collections.sort(results, cmpAfter);
      } else if (sortkeyBefore != null) {
        Collections.sort(results, cmpBefore);
      }
      if (results.size() > maxLimit) {
        moreResults = true;
      }
      int limit = limits.get(i);
      if (limit < results.size()) {
        results = results.subList(0, limit);
      }
      if (sortkeyAfter != null) {
        Collections.reverse(results);
      }
      out.add(results);
    }
    return out;
  }

  public void query(String queryString) throws IOException {
    out = new PrintWriter( //
        new BufferedWriter( //
            new OutputStreamWriter(outputStream, "UTF-8")));
    try {
      if (isDisabled()) {
        ErrorMessage m = new ErrorMessage();
        m.message = "query disabled";
        show(m);
        return;
      }

      try {
        final QueryStatsAttribute stats = new QueryStatsAttribute();
        stats.runTimeMilliseconds = TimeUtil.nowMs();

        List<ChangeData> results = queryChanges(queryString);
        ChangeAttribute c = null;
        for (ChangeData d : results) {
          ChangeControl cc = d.changeControl().forUser(user);

          LabelTypes labelTypes = cc.getLabelTypes();
          c = eventFactory.asChangeAttribute(d.change());
          eventFactory.extend(c, d.change());

          if (!trackingFooters.isEmpty()) {
            eventFactory.addTrackingIds(c,
                trackingFooters.extract(d.commitFooters()));
          }

          if (includeAllReviewers) {
            eventFactory.addAllReviewers(c, d.notes());
          }

          if (includeSubmitRecords) {
            PatchSet.Id psId = d.change().currentPatchSetId();
            PatchSet patchSet = db.get().patchSets().get(psId);
            List<SubmitRecord> submitResult = cc.canSubmit( //
                db.get(), patchSet, null, false, true, true);
            eventFactory.addSubmitRecords(c, submitResult);
          }

          if (includeCommitMessage) {
            eventFactory.addCommitMessage(c, d.commitMessage());
          }

          if (includePatchSets) {
            if (includeFiles) {
              eventFactory.addPatchSets(c, d.patches(),
                includeApprovals ? d.approvals().asMap() : null,
                includeFiles, d.change(), labelTypes);
            } else {
              eventFactory.addPatchSets(c, d.patches(),
                  includeApprovals ? d.approvals().asMap() : null,
                  labelTypes);
            }
          }

          if (includeCurrentPatchSet) {
            PatchSet current = d.currentPatchSet();
            if (current != null) {
              c.currentPatchSet = eventFactory.asPatchSetAttribute(current);
              eventFactory.addApprovals(c.currentPatchSet,
                  d.currentApprovals(), labelTypes);

              if (includeFiles) {
                eventFactory.addPatchSetFileNames(c.currentPatchSet,
                    d.change(), d.currentPatchSet());
              }
            }
          }

          if (includeComments) {
            eventFactory.addComments(c, d.messages());
            if (includePatchSets) {
              for (PatchSetAttribute attribute : c.patchSets) {
                eventFactory.addPatchSetComments(attribute,  d.comments());
              }
            }
          }

          if (includeDependencies) {
            eventFactory.addDependencies(c, d.change());
          }

          show(c);
        }

        stats.rowCount = results.size();
        if (moreResults) {
          stats.resumeSortKey = c.sortKey;
        }
        stats.runTimeMilliseconds =
            TimeUtil.nowMs() - stats.runTimeMilliseconds;
        show(stats);
      } catch (OrmException err) {
        log.error("Cannot execute query: " + queryString, err);

        ErrorMessage m = new ErrorMessage();
        m.message = "cannot query database";
        show(m);

      } catch (QueryParseException e) {
        ErrorMessage m = new ErrorMessage();
        m.message = e.getMessage();
        show(m);
      } catch (NoSuchChangeException e) {
        log.error("Missing change: " + e.getMessage(), e);
        ErrorMessage m = new ErrorMessage();
        m.message = "missing change " + e.getMessage();
        show(m);
      }
    } finally {
      try {
        out.flush();
      } finally {
        out = null;
      }
    }
  }

  boolean isDisabled() {
    return maxLimit <= 0;
  }

  private int limit(Predicate<ChangeData> s) {
    int n = Objects.firstNonNull(ChangeQueryBuilder.getLimit(s), maxLimit);
    return limit > 0 ? Math.min(n, limit) + 1 : n + 1;
  }

  private Predicate<ChangeData> parseQuery(String queryString,
      final Predicate<ChangeData> visibleToMe) throws QueryParseException {
    Predicate<ChangeData> q = queryBuilder.parse(queryString);
    if (queryBuilder.supportsSortKey() && !ChangeQueryBuilder.hasSortKey(q)) {
      if (sortkeyBefore != null) {
        q = Predicate.and(q, queryBuilder.sortkey_before(sortkeyBefore));
      } else if (sortkeyAfter != null) {
        q = Predicate.and(q, queryBuilder.sortkey_after(sortkeyAfter));
      } else {
        q = Predicate.and(q, queryBuilder.sortkey_before("z"));
      }
    }
    return Predicate.and(q,
        queryBuilder.limit(limit > 0 ? Math.min(limit, maxLimit) + 1 : maxLimit),
        visibleToMe);
  }

  private void show(Object data) {
    switch (outputFormat) {
      default:
      case TEXT:
        if (data instanceof ChangeAttribute) {
          out.print("change ");
          out.print(((ChangeAttribute) data).id);
          out.print("\n");
          showText(data, 1);
        } else {
          showText(data, 0);
        }
        out.print('\n');
        break;

      case JSON:
        out.print(gson.toJson(data));
        out.print('\n');
        break;
    }
  }

  private void showText(Object data, int depth) {
    for (Field f : fieldsOf(data.getClass())) {
      Object val;
      try {
        val = f.get(data);
      } catch (IllegalArgumentException err) {
        continue;
      } catch (IllegalAccessException err) {
        continue;
      }
      if (val == null) {
        continue;
      }

      showField(f.getName(), val, depth);
    }
  }

  private String indent(int spaces) {
    if (spaces == 0) {
      return "";
    } else {
      return String.format("%" + spaces + "s", " ");
    }
  }

  private void showField(String field, Object value, int depth) {
    final int spacesDepthRatio = 2;
    String indent = indent(depth * spacesDepthRatio);
    out.print(indent);
    out.print(field);
    out.print(':');
    if (value instanceof String && ((String) value).contains("\n")) {
      out.print(' ');
      // Idention for multi-line text is
      // current depth indetion + length of field + length of ": "
      indent = indent(indent.length() + field.length() + spacesDepthRatio);
      out.print(((String) value).replaceAll("\n", "\n" + indent).trim());
      out.print('\n');
    } else if (value instanceof Long && isDateField(field)) {
      out.print(' ');
      out.print(sdf.format(new Date(((Long) value) * 1000L)));
      out.print('\n');
    } else if (isPrimitive(value)) {
      out.print(' ');
      out.print(value);
      out.print('\n');
    } else if (value instanceof Collection) {
      out.print('\n');
      boolean firstElement = true;
      for (Object thing : ((Collection<?>) value)) {
        // The name of the collection was initially printed at the beginning
        // of this routine.  Beginning at the second sub-element, reprint
        // the collection name so humans can separate individual elements
        // with less strain and error.
        //
        if (firstElement) {
          firstElement = false;
        } else {
          out.print(indent);
          out.print(field);
          out.print(":\n");
        }
        if (isPrimitive(thing)) {
          out.print(' ');
          out.print(value);
          out.print('\n');
        } else {
          showText(thing, depth + 1);
        }
      }
    } else {
      out.print('\n');
      showText(value, depth + 1);
    }
  }

  private static boolean isPrimitive(Object value) {
    return value instanceof String //
        || value instanceof Number //
        || value instanceof Boolean //
        || value instanceof Enum;
  }

  private static boolean isDateField(String name) {
    return "lastUpdated".equals(name) //
        || "grantedOn".equals(name) //
        || "timestamp".equals(name) //
        || "createdOn".equals(name);
  }

  private List<Field> fieldsOf(Class<?> type) {
    List<Field> r = new ArrayList<>();
    if (type.getSuperclass() != null) {
      r.addAll(fieldsOf(type.getSuperclass()));
    }
    r.addAll(Arrays.asList(type.getDeclaredFields()));
    return r;
  }

  static class ErrorMessage {
    public final String type = "error";
    public String message;
  }
}
