package com.codeborne.selenide.junit5;

import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.Screenshots;
import com.codeborne.selenide.ex.UIAssertionError;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

import java.lang.reflect.Method;
import java.util.Optional;
import java.util.logging.Logger;

import static com.codeborne.selenide.WebDriverRunner.driver;
import static com.codeborne.selenide.ex.ErrorMessages.screenshot;

/**
 * Use this class to automatically take screenshots in case of ANY errors in tests (not only Selenide errors).
 *
 * How to use in Java:
 * <pre>
 * {@code
 *    @ExtendWith({ScreenShooterExtension.class})
 *    public class MyTest {...}
 * }
 * </pre>
 *
 * How to use in Java (with customization):
 * <pre>
 * {@code
 *   public class MyTest {
 *     @RegisterExtension
 *     static ScreenShooterExtension screenshotEmAll = new ScreenShooterExtension(true);
 *     ...
 *   }
 * }
 * </pre>
 *
 * How to use in Kotlin:
 *
 * <pre>
 * {@code
 * public class MyTest {
 *   companion object {
 *     @JvmField
 *     @RegisterExtension
 *     val screenshotEmAll: ScreenShooterExtension = ScreenShooterExtension(true);
 *   }
 *   ...
 * }
 * }
 * </pre>
 *
 * @author Aliaksandr Rasolka
 * @since 4.12.2
 */
public class ScreenShooterExtension implements BeforeAllCallback, AfterEachCallback, AfterAllCallback {
  private static final Logger log = Logger.getLogger(ScreenShooterExtension.class.getName());

  private final boolean captureSuccessfulTests;

  public ScreenShooterExtension() {
    this(false);
  }

  /**
   * @param captureSuccessfulTests param that indicate if need to capture successful tests
   */
  public ScreenShooterExtension(final boolean captureSuccessfulTests) {
    this.captureSuccessfulTests = captureSuccessfulTests;
  }

  /**
   * One-liner to configure Configuration.reportsFolder property.
   *
   * @param folderWithScreenshots Folder to put screenshots to
   *
   * @return current extension instance
   */
  public ScreenShooterExtension to(final String folderWithScreenshots) {
    Configuration.reportsFolder = folderWithScreenshots;
    return this;
  }

  @Override
  public void beforeAll(final ExtensionContext context) {
    final Optional<Class<?>> testClass = context.getTestClass();
    final String className = testClass.isPresent()
      ? testClass.get().getName()
      : "EmptyClass";
    final Optional<Method> testMethod = context.getTestMethod();
    final String methodName = testMethod.isPresent()
      ? testMethod.get().getName()
      : "emptyMethod";
    Screenshots.startContext(className, methodName);
  }

  @Override
  public void afterEach(final ExtensionContext context) {
    if (captureSuccessfulTests) {
      log.info(screenshot(driver()));
    } else {
      context.getExecutionException().ifPresent(error -> {
        if (!(error instanceof UIAssertionError)) {
          log.info(screenshot(driver()));
        }
      });
    }
  }

  @Override
  public void afterAll(final ExtensionContext context) {
    Screenshots.finishContext();
  }
}

@@ -1157,32 +1157,34 @@
 :%0A *%0A * %3Cpre%3E%0A *
+  
  %7B@code%0A * publi
@@ -1177,16 +1177,70 @@
 @code%0A *
+     @ExtendWith(ScreenShooterExtension::class)%0A *    
  public 
@@ -1253,19 +1253,140 @@
 MyTest %7B
+...%7D
 %0A *
+   %7D%0A * %3C/pre%3E%0A *%0A * How to use in Kotlin (with customization):%0A *%0A * %3Cpre%3E%0A * %7B@code%0A *   public class MyTest %7B%0A *  
    compa
@@ -1406,16 +1406,18 @@
 %0A *     
+ 
+ 
 @JvmFiel
@@ -1420,16 +1420,18 @@
 Field%0A *
+  
      @Re
@@ -1444,24 +1444,26 @@
 Extension%0A *
+  
      val scr
@@ -1540,21 +1540,27 @@
 *   
+  
 %7D%0A *   
+ 
+ 
 ...%0A *
+  
  %7D%0A 

update javadoc for Kotlin