/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.idea.blaze.base.scope;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * Scoped operation context.
 */
public class BlazeContext {
  @Nullable
  private BlazeContext parentContext;

  @NotNull
  private final List<BlazeScope> scopes = Lists.newArrayList();

  @NotNull
  private final ArrayListMultimap<Class<? extends Output>, OutputSink<?>> outputSinks = ArrayListMultimap.create();

  boolean isEnding;

  boolean isCancelled;

  private int holdCount;

  private boolean hasErrors;

  private boolean propagatesErrors = true;

  public BlazeContext() {
    this(null);
  }

  public BlazeContext(@Nullable BlazeContext parentContext) {
    this.parentContext = parentContext;
  }

  public BlazeContext push(@NotNull BlazeScope scope) {
    scopes.add(scope);
    scope.onScopeBegin(this);
    return this;
  }

  /**
   * Ends the context scope.
   */
  public void endScope() {
    if (isEnding || holdCount > 0) {
      return;
    }
    isEnding = true;
    for (int i = scopes.size() - 1; i >= 0; i--) {
      scopes.get(i).onScopeEnd(this);
    }

    if (parentContext != null && hasErrors && propagatesErrors) {
      parentContext.setHasError();
    }
  }

  /**
   * Requests cancellation of the operation.
   * <p/>
   * <p>Each context holder must handle cancellation individually.
   */
  public void setCancelled() {
    if (isEnding || isCancelled) {
      return;
    }

    isCancelled = true;

    if (parentContext != null) {
      parentContext.setCancelled();
    }
  }

  public void hold() {
    ++holdCount;
  }

  public void release() {
    if (--holdCount == 0) {
      endScope();
    }
  }

  public boolean isEnding() {
    return isEnding;
  }

  public boolean isCancelled() {
    return isCancelled;
  }

  @Nullable
  public <T extends BlazeScope> T getScope(@NotNull Class<T> scopeClass) {
    return getScope(scopeClass, scopes.size());
  }

  @Nullable
  private <T extends BlazeScope> T getScope(@NotNull Class<T> scopeClass, int endIndex) {
    for (int i = endIndex - 1; i >= 0; i--) {
      if (scopes.get(i).getClass() == scopeClass) {
        return scopeClass.cast(scopes.get(i));
      }
    }
    if (parentContext != null) {
      return parentContext.getScope(scopeClass);
    }
    return null;
  }

  @Nullable
  public <T extends BlazeScope> T getParentScope(@NotNull T scope) {
    int index = scopes.indexOf(scope);
    if (index == -1) {
      throw new IllegalArgumentException("Scope does not belong to this context.");
    }
    @SuppressWarnings("unchecked")
    Class<T> scopeClass = (Class<T>)scope.getClass();
    return getScope(scopeClass, index);
  }

  /**
   * Find all instances of {@param scopeClass} that are on the stack starting with this context.
   * That includes this context and all parent contexts recursively.
   *
   * @param scopeClass type of scopes to locate
   * @return The ordered list of all scopes of type {@param scopeClass}, ordered from
   * {@param startingScope} to the root.
   */
  @NotNull
  public <T extends BlazeScope> List<T> getScopes(@NotNull Class<T> scopeClass) {
    List<T> scopesCollector = Lists.newArrayList();
    getScopes(scopesCollector, scopeClass, scopes.size());
    return scopesCollector;
  }

  /**
   * Find all instances of {@param scopeClass} that are above {@param startingScope} on the stack.
   * That includes this context and all parent contexts recursively. {@param startingScope} must be
   * in the this {@link BlazeContext}.
   *
   * @param scopeClass    type of scopes to locate
   * @param startingScope scope to start our search from
   * @return If {@param startingScope} is in this context, the ordered list of all scopes of type
   * {@param scopeClass}, ordered from {@param startingScope} to the root. Otherwise, an empty
   * list.
   */
  @NotNull
  public <T extends BlazeScope> List<T> getScopes(
    @NotNull Class<T> scopeClass,
    @NotNull BlazeScope startingScope) {
    List<T> scopesCollector = Lists.newArrayList();
    int index = scopes.indexOf(startingScope);
    if (index == -1) {
      return scopesCollector;
    }

    // index + 1 so we include startingScope
    getScopes(scopesCollector, scopeClass, index + 1);
    return scopesCollector;
  }

  /**
   * Add matching scopes to {@param scopesCollector}. Search from {@param maxIndex} - 1 to 0.
   */
  @VisibleForTesting
  <T extends BlazeScope> void getScopes(
    @NotNull List<T> scopesCollector,
    @NotNull Class<T> scopeClass,
    int maxIndex) {
    for (int i = maxIndex - 1; i >= 0; --i) {
      BlazeScope scope = scopes.get(i);
      if (scope.getClass() == scopeClass) {
        scopesCollector.add((T)scope);
      }
    }
    if (parentContext != null) {
      parentContext.getScopes(
        scopesCollector,
        scopeClass,
        parentContext.scopes.size());
    }
  }

  public <T extends Output> BlazeContext addOutputSink(@NotNull Class<T> outputClass,
                                               @NotNull OutputSink<T> outputSink) {
    outputSinks.put(outputClass, outputSink);
    return this;
  }

  /**
   * Produces output by sending it to any registered sinks.
   */
  @SuppressWarnings("unchecked")
  public synchronized <T extends Output> void output(@NotNull T output) {
    Class<? extends Output> outputClass = output.getClass();
    List<OutputSink<?>> outputSinks = this.outputSinks.get(outputClass);

    boolean continuePropagation = true;
    for (int i = outputSinks.size() - 1; i >= 0; --i) {
      OutputSink<?> outputSink = outputSinks.get(i);
      OutputSink.Propagation propagation = ((OutputSink<T>)outputSink).onOutput(output);
      continuePropagation = propagation == OutputSink.Propagation.Continue;
      if (!continuePropagation) {
        break;
      }
    }
    if (continuePropagation && parentContext != null) {
      parentContext.output(output);
    }
  }

  /**
   * Sets the error state.
   * <p/>
   * <p>The error state will be propagated to any parents.
   */
  public void setHasError() {
    this.hasErrors = true;
  }

  /**
   * Returns true if there were errors
   */
  public boolean hasErrors() {
    return hasErrors;
  }

  public boolean isRoot() {
    return parentContext == null;
  }

  /**
   * Returns true if no errors and isn't cancelled.
   */
  public boolean shouldContinue() {
    return !hasErrors() && !isCancelled();
  }

  /**
   * Sets whether errors are propagated to the parent context.
   */
  public void setPropagatesErrors(boolean propagatesErrors) {
    this.propagatesErrors = propagatesErrors;
  }
}
