// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import java.io.IOException;
import java.nio.file.FileSystemException;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

public abstract class ExceptionUtils {

  public static final int STATUS_ERROR = 1;

  public static void withConsumeResourceHandler(
      Reporter reporter, StringConsumer consumer, String data) {
    withConsumeResourceHandler(reporter, handler -> consumer.accept(data, handler));
  }

  public static void withConsumeResourceHandler(
      Reporter reporter, Consumer<DiagnosticsHandler> consumer) {
    // Unchecked exceptions simply propagate out, aborting the compilation forcefully.
    consumer.accept(reporter);
    // Fail fast for now. We might consider delaying failure since consumer failure does not affect
    // the compilation. We might need to be careful to correctly identify errors so as to exit
    // compilation with an error code.
    reporter.failIfPendingErrors();
  }

  public interface CompileAction {
    void run() throws IOException, CompilationError, ResourceException;
  }

  public static void withD8CompilationHandler(Reporter reporter, CompileAction action)
      throws CompilationFailedException {
    withCompilationHandler(reporter, action);
  }

  public static void withR8CompilationHandler(Reporter reporter, CompileAction action)
      throws CompilationFailedException {
    withCompilationHandler(reporter, action);
  }

  public static void withMainDexListHandler(
      Reporter reporter, CompileAction action) throws CompilationFailedException {
    withCompilationHandler(reporter, action);
  }

  public static void withCompilationHandler(Reporter reporter, CompileAction action)
      throws CompilationFailedException {
    try {
      try {
        action.run();
      } catch (IOException e) {
        throw reporter.fatalError(new ExceptionDiagnostic(e, extractIOExceptionOrigin(e)));
      } catch (CompilationError e) {
        throw reporter.fatalError(e);
      } catch (ResourceException e) {
        throw reporter.fatalError(new ExceptionDiagnostic(e, e.getOrigin()));
      } catch (AssertionError e) {
        throw reporter.fatalError(new ExceptionDiagnostic(e, Origin.unknown()));
      }
      reporter.failIfPendingErrors();
    } catch (AbortException e) {
      throw new CompilationFailedException(e);
    }
  }

  public interface MainAction {
    void run() throws CompilationFailedException;
  }

  public static void withMainProgramHandler(MainAction action) {
    try {
      action.run();
    } catch (CompilationFailedException | AbortException e) {
      // Detail of the errors were already reported
      System.err.println("Compilation failed");
      System.exit(STATUS_ERROR);
    } catch (RuntimeException e) {
      System.err.println("Compilation failed with an internal error.");
      Throwable cause = e.getCause() == null ? e : e.getCause();
      cause.printStackTrace();
      System.exit(STATUS_ERROR);
    }
  }

  // We should try to avoid the use of this extraction as it signifies a point where we don't have
  // enough context to associate a specific origin with an IOException. Concretely, we should move
  // towards always catching IOException and rethrowing CompilationError with proper origins.
  public static Origin extractIOExceptionOrigin(IOException e) {
    if (e instanceof FileSystemException) {
      FileSystemException fse = (FileSystemException) e;
      if (fse.getFile() != null && !fse.getFile().isEmpty()) {
        return new PathOrigin(Paths.get(fse.getFile()));
      }
    }
    return Origin.unknown();
  }

  public static RuntimeException unwrapExecutionException(ExecutionException executionException) {
    Throwable cause = executionException.getCause();
    if (cause instanceof Error) {
      // add original exception as suppressed exception to provide the original stack trace
      cause.addSuppressed(executionException);
      throw (Error) cause;
    } else if (cause instanceof RuntimeException) {
      cause.addSuppressed(executionException);
      throw (RuntimeException) cause;
    } else {
      throw new RuntimeException(executionException.getMessage(), cause);
    }
  }
}
