// 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 static java.util.stream.Collectors.toList;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.task.TaskConfig.External;
import com.googlesource.gerrit.plugins.task.TaskConfig.NamesFactory;
import com.googlesource.gerrit.plugins.task.TaskConfig.NamesFactoryType;
import com.googlesource.gerrit.plugins.task.TaskConfig.Task;
import com.googlesource.gerrit.plugins.task.TaskConfig.TasksFactory;
import com.googlesource.gerrit.plugins.task.extensions.PluginProvidedTaskNamesFactory;
import com.googlesource.gerrit.plugins.task.properties.Properties;
import com.googlesource.gerrit.plugins.task.statistics.HitHashMap;
import com.googlesource.gerrit.plugins.task.statistics.HitHashMapOfCollection;
import com.googlesource.gerrit.plugins.task.statistics.StatisticsMap;
import com.googlesource.gerrit.plugins.task.statistics.StopWatch;
import com.googlesource.gerrit.plugins.task.statistics.TracksStatistics;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.util.StringUtils;

/**
 * Add structure to access the task definitions from the config as a tree.
 *
 * <p>This class is a "middle" representation of the task tree. The task config is represented as a
 * lazily loaded tree, and much of the tree validity is enforced at this layer.
 */
public class TaskTree {
  private static final FluentLogger log = FluentLogger.forEnclosingClass();

  public interface Factory {
    TaskTree create(@Assisted TaskConfigCache taskConfigCache);
  }

  @FunctionalInterface
  public interface NodeFactory {
    Node create(NodeList parent, Task definition) throws Exception;
  }

  public static class Statistics {
    public Object definitionsPerSubSectionCache;
    public Object definitionsByBranchBySubSectionCache;
    public Object changesByNamesFactoryQueryCache;
    public Properties.Statistics properties;
    public transient int summaryCount;
  }

  protected static final String TASK_DIR = "task";

  protected final AccountResolver accountResolver;
  protected final AllUsersNameProvider allUsers;
  protected final CurrentUser user;
  protected final PredicateCache predicateCache;
  protected final MatchCache matchCache;
  protected final Preloader preloader;
  protected final TaskConfigCache taskConfigCache;
  protected final TaskExpression.Factory taskExpressionFactory;
  protected final DynamicMap<DynamicOptions.DynamicBean> dynamicBeans;
  protected final NodeList root = new NodeList();
  protected final Provider<ChangeQueryBuilder> changeQueryBuilderProvider;
  protected final Provider<ChangeQueryProcessor> changeQueryProcessorProvider;
  protected final StatisticsMap<String, List<ChangeData>> changesByNamesFactoryQuery =
      new HitHashMap<>();
  protected final StatisticsMap<SubSectionKey, List<Task>> definitionsBySubSection =
      new HitHashMapOfCollection<>();
  protected final StatisticsMap<SubSectionKey, Map<BranchNameKey, List<Task>>>
      definitionsByBranchBySubSection = new HitHashMap<>();

  protected ChangeData changeData;
  protected Statistics statistics;

  @Inject
  public TaskTree(
      AccountResolver accountResolver,
      AllUsersNameProvider allUsers,
      AnonymousUser anonymousUser,
      CurrentUser user,
      Provider<ChangeQueryBuilder> changeQueryBuilderProvider,
      Provider<ChangeQueryProcessor> changeQueryProcessorProvider,
      PredicateCache predicateCache,
      TaskExpression.Factory taskExpressionFactory,
      Preloader.Factory preloaderFactory,
      @Assisted TaskConfigCache taskConfigCache,
      DynamicMap<DynamicOptions.DynamicBean> dynamicBeans) {
    this.accountResolver = accountResolver;
    this.allUsers = allUsers;
    this.user = user != null ? user : anonymousUser;
    this.changeQueryProcessorProvider = changeQueryProcessorProvider;
    this.changeQueryBuilderProvider = changeQueryBuilderProvider;
    this.predicateCache = predicateCache;
    this.matchCache = new MatchCache(predicateCache);
    this.taskConfigCache = taskConfigCache;
    this.taskExpressionFactory = taskExpressionFactory;
    this.preloader = preloaderFactory.create(taskConfigCache);
    this.dynamicBeans = dynamicBeans;
  }

  public List<Node> getRootNodes(ChangeData changeData)
      throws ConfigInvalidException, IOException, StorageException {
    this.changeData = changeData;
    root.path = Collections.emptyList();
    root.duplicateKeys = Collections.emptyList();
    return root.getSubNodes();
  }

  protected class NodeList {
    protected NodeList parent = null;
    protected Collection<String> path;
    protected Collection<String> duplicateKeys;
    protected Map<TaskKey, Node> cachedNodeByTask = new HashMap<>();
    protected List<Node> cachedNodes;

    protected List<Node> getSubNodes()
        throws ConfigInvalidException, IOException, StorageException {
      if (cachedNodes != null) {
        return refresh(cachedNodes);
      }
      return cachedNodes = loadSubNodes();
    }

    protected List<Node> loadSubNodes()
        throws ConfigInvalidException, IOException, StorageException {
      return new SubNodeFactory().createFromPreloaded(preloader.getRootTasks());
    }

    public ChangeData getChangeData() {
      return TaskTree.this.changeData;
    }

    protected boolean isTrusted() {
      return true;
    }

    protected class SubNodeFactory {
      protected Set<String> names = new HashSet<>();

      public List<Node> createFromPreloaded(List<Task> defs) {
        List<Node> nodes = new ArrayList<>();
        for (Task def : defs) {
          nodes.add(createFromPreloaded(def));
        }
        return nodes;
      }

      public Node createFromPreloaded(Task def) {
        return createFromPreloaded(def, (parent, definition) -> new Node(parent, definition));
      }

      public Node createFromPreloaded(Task def, ChangeData changeData) {
        return createFromPreloaded(
            def,
            (parent, definition) ->
                new Node(parent, definition) {
                  @Override
                  public ChangeData getChangeData() {
                    return changeData;
                  }

                  @Override
                  public boolean isChange() {
                    return true;
                  }
                });
      }

      protected Node createFromPreloaded(Task def, NodeFactory nodeFactory) {
        if (def != null) {
          try {
            Node node = cachedNodeByTask.get(def.key());
            boolean isRefreshNeeded = node != null;
            if (node == null) {
              node = nodeFactory.create(NodeList.this, def);
            }

            if (names.add(def.name())) {
              // names check above detects duplicate subtasks
              if (isRefreshNeeded) {
                node.refreshTask();
              }
              return node;
            }
          } catch (Exception e) {
          }
        }
        return createInvalid();
      }

      protected Node createInvalid() {
        return new Node().new Invalid();
      }
    }
  }

  public class Node extends NodeList {
    public class Invalid extends Node {
      @Override
      public void refreshTask() {}

      @Override
      public Task getDefinition() {
        return null;
      }
    }

    public Task task;
    public boolean isDuplicate;

    protected Properties.Statistics propertiesStatistics;
    protected final Properties properties;
    protected final TaskKey taskKey;
    protected StatisticsMap<BranchNameKey, List<Node>> nodesByBranch;
    protected boolean hasUnfilterableSubNodes = false;

    protected Node() { // Only for Invalid
      taskKey = null;
      properties = null;
    }

    public Node(NodeList parent, Task task) {
      this.parent = parent;
      taskKey = task.key();
      properties = new Properties(this, task);
      refreshTask();
    }

    public String key() {
      return String.valueOf(getChangeData().getId().get()) + TaskConfig.SEP + taskKey;
    }

    public List<Node> getSubNodes() throws IOException, StorageException, ConfigInvalidException {
      if (cachedNodes != null) {
        return refresh(cachedNodes);
      }
      List<Node> nodes = loadSubNodes();
      if (!properties.isSubNodeReloadRequired()) {
        if (!isChange()) {
          return cachedNodes = nodes;
        }
        definitionsBySubSection.computeIfAbsentTimed(
            task.key().subSection(),
            k -> nodes.stream().map(n -> n.getDefinition()).collect(toList()),
            task.isVisible);
      } else {
        hasUnfilterableSubNodes = true;
        cachedNodeByTask.clear();
        nodes.stream()
            .filter(n -> !(n instanceof Invalid) && !n.isChange())
            .forEach(n -> cachedNodeByTask.put(n.task.key(), n));
      }
      return nodes;
    }

    public List<Node> getApplicableSubNodes()
        throws IOException, StorageException, ConfigInvalidException {
      return hasUnfilterableSubNodes ? getSubNodes() : new ApplicableNodeFilter().getSubNodes();
    }

    @Override
    protected List<Node> loadSubNodes()
        throws IOException, StorageException, ConfigInvalidException {
      List<Task> cachedDefinitions = definitionsBySubSection.get(task.key().subSection());
      if (cachedDefinitions != null) {
        return new SubNodeFactory().createFromPreloaded(cachedDefinitions);
      }
      List<Node> nodes = new SubNodeAdder().getSubNodes();
      properties.expansionComplete();
      return nodes;
    }

    /* The task needs to be refreshed before a node is used, however
    subNode refreshing can wait until they are fetched since they may
    not be needed. */
    public void refreshTask() {
      this.path = new LinkedList<>(parent.path);
      String key = key();
      isDuplicate = path.contains(key);
      path.add(key);

      if (statistics != null) {
        properties.setStatisticsConsumer(
            s -> statistics.properties = (propertiesStatistics = s).sum(statistics.properties));
      }
      this.task = properties.getTask(getChangeData());

      this.duplicateKeys = new LinkedList<>(parent.duplicateKeys);
      if (task.duplicateKey != null) {
        isDuplicate |= duplicateKeys.contains(task.duplicateKey);
        duplicateKeys.add(task.duplicateKey);
      }
    }

    public Properties getParentProperties() {
      return (parent instanceof Node) ? ((Node) parent).properties : Properties.EMPTY;
    }

    @Override
    protected boolean isTrusted() {
      return parent.isTrusted() && !task.isMasqueraded;
    }

    @Override
    public ChangeData getChangeData() {
      return parent.getChangeData();
    }

    public Task getDefinition() {
      return properties.isTaskRefreshRequired() ? properties.origTask : task;
    }

    public boolean isChange() {
      return false;
    }

    public boolean match(String query) throws StorageException, QueryParseException {
      return matchCache.match(getChangeData(), query, task.isVisible);
    }

    public Boolean matchOrNull(String query) {
      return matchCache.matchOrNull(getChangeData(), query, task.isVisible);
    }

    protected class SubNodeAdder {
      protected List<Node> nodes = new ArrayList<>();
      protected SubNodeFactory factory = new SubNodeFactory();

      public List<Node> getSubNodes() throws IOException, StorageException, ConfigInvalidException {
        addSubTasks();
        addSubTasksFactoryTasks();
        addSubTasksFiles();
        addSubTasksExternals();
        return nodes;
      }

      protected void addSubTasks() throws IOException, StorageException {
        for (ConfigSourcedValue configSourcedValue : task.subTasks) {
          try {
            Optional<Task> def =
                preloader.getOptionalTask(
                    taskExpressionFactory.create(
                        configSourcedValue.sourceFile(), configSourcedValue.value()));
            if (def.isPresent()) {
              addPreloaded(def.get());
            }
          } catch (ConfigInvalidException e) {
            addInvalidNode();
          }
        }
      }

      protected void addSubTasksFiles() {
        for (ConfigSourcedValue configSourcedValue : task.subTasksFiles) {
          try {
            addPreloaded(
                preloader.getTasks(
                    FileKey.create(
                        configSourcedValue.sourceFile().branch(),
                        resolveTaskFileName(configSourcedValue.value()))));
          } catch (ConfigInvalidException | IOException e) {
            addInvalidNode();
          }
        }
      }

      protected void addSubTasksExternals() throws StorageException {
        for (ConfigSourcedValue configSourcedValue : task.subTasksExternals) {
          try {
            External ext =
                taskConfigCache
                    .getTaskConfig(configSourcedValue.sourceFile())
                    .getExternal(configSourcedValue.value());
            if (ext == null) {
              addInvalidNode();
            } else {
              addPreloaded(getPreloadedTasks(ext));
            }
          } catch (ConfigInvalidException | IOException e) {
            addInvalidNode();
          }
        }
      }

      protected void addSubTasksFactoryTasks()
          throws IOException, StorageException, ConfigInvalidException {
        for (ConfigSourcedValue configSourcedValue : task.subTasksFactories) {
          TasksFactory tasksFactory =
              taskConfigCache
                  .getTaskConfig(configSourcedValue.sourceFile())
                  .getTasksFactory(configSourcedValue.value());
          if (tasksFactory != null) {
            NamesFactory namesFactory =
                taskConfigCache
                    .getTaskConfig(configSourcedValue.sourceFile())
                    .getNamesFactory(tasksFactory.namesFactory);
            if (namesFactory != null && namesFactory.type != null) {
              namesFactory = properties.getNamesFactory(namesFactory);
              switch (NamesFactoryType.getNamesFactoryType(namesFactory.type)) {
                case STATIC:
                  addStaticTypeTasks(tasksFactory, namesFactory);
                  continue;
                case CHANGE:
                  addChangeTypeTasks(tasksFactory, namesFactory);
                  continue;
                case PLUGIN:
                  addPluginTypeTasks(tasksFactory, namesFactory);
                  continue;
              }
            }
          }
          addInvalidNode();
        }
      }

      protected void addStaticTypeTasks(TasksFactory tasksFactory, NamesFactory namesFactory)
          throws IOException, StorageException {
        for (String name : namesFactory.names) {
          if (StringUtils.isEmptyOrNull(name)) {
            addInvalidNode();
          } else {
            try {
              addPreloaded(preloader.preload(task.config.new Task(tasksFactory, name)));
            } catch (ConfigInvalidException e) {
              addInvalidNode();
            }
          }
        }
      }

      protected void addChangeTypeTasks(TasksFactory tasksFactory, NamesFactory namesFactory)
          throws IOException {
        try {
          if (namesFactory.changes != null) {
            for (ChangeData changeData : query(namesFactory.changes, task.isVisible)) {
              addPreloaded(
                  preloader.preload(
                      task.config.new Task(tasksFactory, changeData.getId().toString())),
                  changeData);
            }
            return;
          }
        } catch (StorageException e) {
          log.atSevere().withCause(e).log(
              "Running changes query '%s' failed", namesFactory.changes);
        } catch (QueryParseException | ConfigInvalidException e) {
        }
        addInvalidNode();
      }

      protected void addPluginTypeTasks(TasksFactory tasksFactory, NamesFactory namesFactory)
          throws IOException {
        if (namesFactory.plugin != null && namesFactory.provider != null) {
          List<String> names;
          try {
            PluginProvidedTaskNamesFactory providedTaskNamesFactory =
                PluginProvidedTaskNamesFactory.getProxyInstance(
                    dynamicBeans, namesFactory.plugin, namesFactory.provider);
            names = providedTaskNamesFactory.getNames(getChangeData(), namesFactory.args);
          } catch (Exception e) {
            log.atSevere().withCause(e).log("Failed to get plugin provided task names");
            addInvalidNode();
            return;
          }
          for (String name : names) {
            try {
              addPreloaded(preloader.preload(task.config.new Task(tasksFactory, name)));
            } catch (ConfigInvalidException e) {
              addInvalidNode();
            }
          }
          return;
        }
        addInvalidNode();
      }

      public void addPreloaded(List<Task> defs) {
        nodes.addAll(factory.createFromPreloaded(defs));
      }

      public void addPreloaded(Task def, ChangeData changeData) {
        nodes.add(factory.createFromPreloaded(def, changeData));
      }

      public void addPreloaded(Task def) {
        nodes.add(factory.createFromPreloaded(def));
      }

      public void addInvalidNode() {
        nodes.add(factory.createInvalid());
      }

      protected List<Task> getPreloadedTasks(External external)
          throws ConfigInvalidException, IOException, StorageException {
        return preloader.getTasks(
            FileKey.create(resolveUserBranch(external.user), resolveTaskFileName(external.file)));
      }
    }

    public class ApplicableNodeFilter {
      protected BranchNameKey branch = getChangeData().change().getDest();
      protected SubSectionKey subSection = task.key.subSection();
      protected Map<BranchNameKey, List<Task>> definitionsByBranch =
          definitionsByBranchBySubSection.get(subSection);

      public ApplicableNodeFilter() throws StorageException {}

      public List<Node> getSubNodes() throws IOException, StorageException, ConfigInvalidException {
        if (nodesByBranch != null) {
          List<Node> nodes = nodesByBranch.get(branch);
          if (nodes != null) {
            return refresh(nodes);
          }
        }
        if (definitionsByBranch != null) {
          List<Task> branchDefinitions = definitionsByBranch.get(branch);
          if (branchDefinitions != null) {
            return new SubNodeFactory().createFromPreloaded(branchDefinitions);
          }
        }
        List<Node> nodes = Node.this.getSubNodes();
        if (isChange()
            && definitionsByBranch == null
            && definitionsByBranchBySubSection.containsKey(subSection)) {
          hasUnfilterableSubNodes = true;
        }

        if (!hasUnfilterableSubNodes && !nodes.isEmpty()) {
          Optional<List<Node>> filterable = getOptionalApplicableForBranch(nodes);
          if (filterable.isPresent()) {
            if (!isChange()) {
              if (nodesByBranch == null) {
                nodesByBranch = initStatistics(new HitHashMapOfCollection<>());
              }
              nodesByBranch.put(branch, filterable.get());
            } else {
              if (definitionsByBranch == null) {
                definitionsByBranch = initStatistics(new HitHashMap<>());
                definitionsByBranchBySubSection.put(subSection, definitionsByBranch);
              }
              definitionsByBranch.put(
                  branch,
                  filterable.get().stream().map(node -> node.getDefinition()).collect(toList()));
            }
            return filterable.get();
          }
          hasUnfilterableSubNodes = true;
          if (isChange()) {
            definitionsByBranchBySubSection.put(subSection, null);
          }
        }
        return nodes;
      }

      protected Optional<List<Node>> getOptionalApplicableForBranch(List<Node> nodes)
          throws StorageException {
        int filterable = 0;
        List<Node> applicableNodes = new ArrayList<>();
        for (Node node : nodes) {
          if (node instanceof Invalid) {
            filterable++;
          } else if (isApplicableCacheableByBranch(node)) {
            filterable++;
            try {
              if (!node.match(node.task.applicable)) {
                // Correctness will not be affected if more nodes are added than necessary
                // (i.e. if isApplicableCacheableByBranch() does not realize a Node is cacheable
                // based on its Branch), but it is incorrect to filter out a Node now that could
                // later be applicable when a property, other than its Change's destination, is
                // altered.
                continue;
              }
            } catch (QueryParseException e) {
            }
          }
          applicableNodes.add(node);
        }
        // Simple heuristic to determine whether storing the filtered nodes is worth it. There
        // is minor evidence to suggest that storing a large list actually hurts performance.
        return (filterable > nodes.size() / 2) ? Optional.of(applicableNodes) : Optional.empty();
      }

      protected boolean isApplicableCacheableByBranch(Node node) {
        String applicable = node.task.applicable;
        if (node.properties.isApplicableRefreshRequired()) {
          return false;
        }
        try {
          return predicateCache.isCacheableByBranch(applicable, task.isVisible);
        } catch (QueryParseException e) {
          return false;
        }
      }
    }
  }

  protected String resolveTaskFileName(String file) throws ConfigInvalidException {
    if (file == null) {
      throw new ConfigInvalidException("External file not defined");
    }
    Path p = Paths.get(TASK_DIR, file);
    if (!p.startsWith(TASK_DIR)) {
      throw new ConfigInvalidException("task file not under " + TASK_DIR + " directory: " + file);
    }
    return p.toString();
  }

  protected BranchNameKey resolveUserBranch(String user)
      throws ConfigInvalidException, IOException, StorageException {
    if (user == null) {
      throw new ConfigInvalidException("External user not defined");
    }
    Account.Id acct;
    try {
      acct = accountResolver.resolve(user).asUnique().account().id();
    } catch (UnprocessableEntityException e) {
      throw new ConfigInvalidException("Cannot resolve user: " + user);
    }
    return BranchNameKey.create(allUsers.get(), RefNames.refsUsers(acct));
  }

  @SuppressWarnings("try")
  public List<ChangeData> query(String query, boolean isVisible)
      throws StorageException, QueryParseException {
    List<ChangeData> changeDataList = changesByNamesFactoryQuery.get(query);
    if (changeDataList == null) {
      try (StopWatch stopWatch =
          changesByNamesFactoryQuery.createLoadingStopWatch(query, isVisible)) {
        changeDataList =
            changeQueryProcessorProvider
                .get()
                .query(changeQueryBuilderProvider.get().parse(query))
                .entities();
      }
      changesByNamesFactoryQuery.put(query, changeDataList);
    }
    return changeDataList;
  }

  public void initStatistics(int summaryCount) {
    statistics = new Statistics();
    statistics.summaryCount = summaryCount;
    definitionsBySubSection.initStatistics(summaryCount);
    definitionsByBranchBySubSection.initStatistics(summaryCount);
    changesByNamesFactoryQuery.initStatistics(summaryCount);
  }

  protected <T extends TracksStatistics> T initStatistics(T tracker) {
    if (statistics != null) {
      tracker.initStatistics(statistics.summaryCount);
    }
    return tracker;
  }

  public Statistics getStatistics() {
    if (statistics != null) {
      statistics.definitionsPerSubSectionCache = definitionsBySubSection.getStatistics();
      statistics.definitionsByBranchBySubSectionCache =
          definitionsByBranchBySubSection.getStatistics();
      statistics.changesByNamesFactoryQueryCache = changesByNamesFactoryQuery.getStatistics();
    }
    return statistics;
  }

  protected static List<Node> refresh(List<Node> nodes) {
    for (Node node : nodes) {
      node.refreshTask();
    }
    return nodes;
  }
}
