package de.dhbwstuttgart.typeinference.unify;

import de.dhbwstuttgart.util.Logger;
import java.io.Writer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;

public record UnifyContext(
  // main logger of a unification
  Logger logger,
  // if the unify algorithm should run in parallel
  boolean parallel,
  // the model for storing calculated results
  UnifyResultModel resultModel,
  // the executor used for thread management in parallel execution
  ExecutorService executor,
  // a generator for new placeholders in this unify context
  PlaceholderRegistry placeholderRegistry,
  // a control structure to cancel the unification early
  UnifyTaskModel usedTasks
) {

  public UnifyContext(
    Logger logger,
    boolean parallel,
    UnifyResultModel resultModel,
    UnifyTaskModel usedTasks,
    ExecutorService executor,
    PlaceholderRegistry placeholderRegistry
  ) {
    this(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
  }

  public UnifyContext(
    Logger logger,
    boolean parallel,
    UnifyResultModel resultModel,
    UnifyTaskModel usedTasks,
    PlaceholderRegistry placeholderRegistry
  ) {
    this(logger, parallel, resultModel, usedTasks, ForkJoinPool.commonPool(), placeholderRegistry);
  }


  /*
   * Shortcuts for creating a similar context with some properties changed. This combined with the final properties
   * causes the UnifyContext to be essentially handled as a
   */

  public UnifyContext newWithLogger(Logger logger) {
    return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
  }

  public UnifyContext newWithParallel(boolean parallel) {
    if (this.parallel == parallel) return this;
    return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
  }

  public UnifyContext newWithExecutor(ExecutorService executor) {
    return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
  }

  public UnifyContext newWithResultModel(UnifyResultModel resultModel) {
    return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
  }

}
