// 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.googlesource.gerrit.plugins.task;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.DynamicOptions.BeanProvider;
import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.task.TaskConfig.Task;
import com.googlesource.gerrit.plugins.task.TaskTree.Node;
import com.googlesource.gerrit.plugins.task.cli.PatchSetArgument;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;

public class TaskAttributeFactory implements ChangeAttributeFactory {
  private static final FluentLogger log = FluentLogger.forEnclosingClass();

  public enum Status {
    INVALID,
    UNKNOWN,
    WAITING,
    READY,
    PASS,
    FAIL;
  }

  public static class TaskAttribute {
    public Boolean applicable;
    public Map<String, String> exported;
    public Boolean hasPass;
    public String hint;
    public Boolean inProgress;
    public String name;
    public Status status;
    public List<TaskAttribute> subTasks;
    public Long evaluationMilliSeconds;

    public TaskAttribute(String name) {
      this.name = name;
    }
  }

  public static class TaskPluginAttribute extends PluginDefinedInfo {
    public List<TaskAttribute> roots = new ArrayList<>();
  }

  protected final TaskTree definitions;
  protected final ChangeQueryBuilder cqb;

  protected final Map<String, Predicate<ChangeData>> predicatesByQuery = new HashMap<>();

  protected Modules.MyOptions options;

  @Inject
  public TaskAttributeFactory(TaskTree definitions, ChangeQueryBuilder cqb) {
    this.definitions = definitions;
    this.cqb = cqb;
  }

  @Override
  public PluginDefinedInfo create(ChangeData c, BeanProvider beanProvider, String plugin) {
    options = (Modules.MyOptions) beanProvider.getDynamicBean(plugin);
    if (options.all || options.onlyApplicable || options.onlyInvalid) {
      for (PatchSetArgument psa : options.patchSetArguments) {
        definitions.masquerade(psa);
      }
      try {
        return createWithExceptions(c);
      } catch (StorageException e) {
        log.atSevere().withCause(e).log("Cannot load tasks for: %s", c);
      }
    }
    return null;
  }

  protected PluginDefinedInfo createWithExceptions(ChangeData c) {
    TaskPluginAttribute a = new TaskPluginAttribute();
    try {
      for (Node node : definitions.getRootNodes()) {
        addApplicableTasks(a.roots, c, node);
      }
    } catch (ConfigInvalidException | IOException e) {
      a.roots.add(invalid());
    }

    if (a.roots.isEmpty()) {
      return null;
    }
    return a;
  }

  protected void addApplicableTasks(List<TaskAttribute> atts, ChangeData c, Node node) {
    try {
      Task def = node.definition;
      TaskAttribute att = new TaskAttribute(def.name);
      if (options.evaluationTime) {
        att.evaluationMilliSeconds = millis();
      }

      boolean applicable = match(c, def.applicable);
      if (!def.isVisible) {
        if (!def.isTrusted || (!applicable && !options.onlyApplicable)) {
          atts.add(unknown());
          return;
        }
      }

      if (applicable || !options.onlyApplicable) {
        att.hasPass = def.pass != null || def.fail != null;
        att.subTasks = getSubTasks(c, node);
        att.status = getStatus(c, def, att);
        if (options.onlyInvalid && !isValidQueries(c, def)) {
          att.status = Status.INVALID;
        }
        boolean groupApplicable = att.status != null;

        if (groupApplicable || !options.onlyApplicable) {
          if (!options.onlyInvalid || att.status == Status.INVALID || att.subTasks != null) {
            if (!options.onlyApplicable) {
              att.applicable = applicable;
            }
            if (def.inProgress != null) {
              att.inProgress = matchOrNull(c, def.inProgress);
            }
            att.hint = getHint(att.status, def);
            att.exported = def.exported;

            if (options.evaluationTime) {
              att.evaluationMilliSeconds = millis() - att.evaluationMilliSeconds;
            }
            atts.add(att);
          }
        }
      }
    } catch (QueryParseException e) {
      atts.add(invalid()); // bad applicability query
    }
  }

  protected long millis() {
    return System.nanoTime() / 1000000;
  }

  protected List<TaskAttribute> getSubTasks(ChangeData c, Node node) {
    List<TaskAttribute> subTasks = new ArrayList<>();
    for (Node subNode : node.getSubNodes()) {
      if (subNode == null) {
        subTasks.add(invalid());
      } else {
        addApplicableTasks(subTasks, c, subNode);
      }
    }
    if (subTasks.isEmpty()) {
      return null;
    }
    return subTasks;
  }

  protected static TaskAttribute invalid() {
    // For security reasons, do not expose the task name without knowing
    // the visibility which is derived from its applicability.
    TaskAttribute a = unknown();
    a.status = Status.INVALID;
    return a;
  }

  protected static TaskAttribute unknown() {
    TaskAttribute a = new TaskAttribute("UNKNOWN");
    a.status = Status.UNKNOWN;
    return a;
  }

  protected boolean isValidQueries(ChangeData c, Task def) {
    try {
      match(c, def.inProgress);
      match(c, def.fail);
      match(c, def.pass);
      return true;
    } catch (StorageException | QueryParseException e) {
      return false;
    }
  }

  protected Status getStatus(ChangeData c, Task def, TaskAttribute a) {
    try {
      return getStatusWithExceptions(c, def, a);
    } catch (QueryParseException e) {
      return Status.INVALID;
    }
  }

  protected Status getStatusWithExceptions(ChangeData c, Task def, TaskAttribute a)
      throws QueryParseException {
    if (isAllNull(def.pass, def.fail, a.subTasks)) {
      // A leaf def has no defined subdefs.
      boolean hasDefinedSubtasks =
          !(def.subTasks.isEmpty()
              && def.subTasksFiles.isEmpty()
              && def.subTasksExternals.isEmpty());
      if (hasDefinedSubtasks) {
        // Remove 'Grouping" tasks (tasks with subtasks but no PASS
        // or FAIL criteria) from the output if none of their subtasks
        // are applicable.  i.e. grouping tasks only really apply if at
        // least one of their subtasks apply.
        return null;
      }
      // A leaf configuration without a PASS or FAIL criteria is a
      // missconfiguration.  Either someone forgot to add subtasks, or
      // they forgot to add a PASS or FAIL criteria.
      return Status.INVALID;
    }

    if (def.fail != null) {
      if (match(c, def.fail)) {
        // A FAIL definition is meant to be a hard blocking criteria
        // (like a CodeReview -2).  Thus, if hard blocked, it is
        // irrelevant what the subtask states, or the PASS criteria are.
        //
        // It is also important that FAIL be useable to indicate that
        // the task has actually executed.  Thus subtask status,
        // including a subtask FAIL should not appear as a FAIL on the
        // parent task.  This means that this is should be the only path
        // to make a task have a FAIL status.
        return Status.FAIL;
      }
      if (def.pass == null) {
        // A task with a FAIL but no PASS criteria is a PASS-FAIL task
        // (they are never "READY").  It didn't fail, so pass.
        return Status.PASS;
      }
    }

    if (a.subTasks != null && !isAll(a.subTasks, Status.PASS)) {
      // It is possible for a subtask's PASS criteria to change while
      // a parent task is executing, or even after the parent task
      // completes.  This can result in the parent PASS criteria being
      // met while one or more of its subtasks no longer meets its PASS
      // criteria (the subtask may now even meet a FAIL criteria).  We
      // never want the parent task to reflect a PASS criteria in these
      // cases, thus we can safely return here without ever evaluating
      // the task's PASS criteria.
      return Status.WAITING;
    }

    if (def.pass != null && !match(c, def.pass)) {
      // Non-leaf tasks with no PASS criteria are supported in order
      // to support "grouping tasks" (tasks with no function aside from
      // organizing tasks).  A task without a PASS criteria, cannot ever
      // be expected to execute (how would you know if it has?), thus a
      // pass criteria is required to possibly even be considered for
      // READY.
      return Status.READY;
    }

    return Status.PASS;
  }

  protected String getHint(Status status, Task def) {
    if (status == Status.READY) {
      return def.readyHint;
    } else if (status == Status.FAIL) {
      return def.failHint;
    }
    return null;
  }

  protected static boolean isAll(Iterable<TaskAttribute> atts, Status state) {
    for (TaskAttribute att : atts) {
      if (att.status != state) {
        return false;
      }
    }
    return true;
  }

  protected boolean match(ChangeData c, String query) throws QueryParseException {
    if (query == null || query.equalsIgnoreCase("true")) {
      return true;
    }
    Predicate<ChangeData> pred = predicatesByQuery.get(query);
    if (pred == null) {
      pred = cqb.parse(query);
      predicatesByQuery.put(query, pred);
    }
    return pred.asMatchable().match(c);
  }

  protected Boolean matchOrNull(ChangeData c, String query) {
    if (query != null) {
      try {
        if (query.equalsIgnoreCase("true")) {
          return true;
        }
        return cqb.parse(query).asMatchable().match(c);
      } catch (StorageException | QueryParseException e) {
      }
    }
    return null;
  }

  protected static boolean isAllNull(Object... vals) {
    for (Object val : vals) {
      if (val != null) {
        return false;
      }
    }
    return true;
  }
}
