package com.codeborne.selenide.impl;

import org.openqa.selenium.InvalidSelectorException;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

import static java.util.Objects.requireNonNull;

@ParametersAreNonnullByDefault
public class Cleanup {
  public static Cleanup of = new Cleanup();

  @CheckReturnValue
  @Nonnull
  public String webdriverExceptionMessage(Throwable webDriverException) {
    return requireNonNull(webdriverExceptionMessage(webDriverException.toString()));
  }

  @CheckReturnValue
  @Nullable
  public String webdriverExceptionMessage(@Nullable String webDriverExceptionInfo) {
    return webDriverExceptionInfo == null || webDriverExceptionInfo.indexOf('\n') == -1 ?
      webDriverExceptionInfo :
      webDriverExceptionInfo
        .substring(0, webDriverExceptionInfo.indexOf('\n'))
        .replaceFirst("(.*)\\(WARNING: The server did not provide any stacktrace.*", "$1")
        .replaceFirst("org\\.openqa\\.selenium\\.(.*)", "$1")
        .trim();
  }

  public boolean isInvalidSelectorError(@Nullable Throwable error) {
    if (error == null) return false;
    if (error instanceof AssertionError) return false;

    String message = error.getMessage();
    if (message == null) return false;

    return (error instanceof InvalidSelectorException && !message.contains("\"Element is not selectable\"")) ||
      isInvalidSelectorMessage(message) ||
      error.getCause() != null && error.getCause() != error && isInvalidSelectorError(error.getCause());
  }

  private boolean isInvalidSelectorMessage(String message) {
    return message.contains("invalid or illegal string was specified") ||
      message.contains("Invalid selector") ||
      message.contains("invalid selector") ||
      message.contains("is not a valid selector") ||
      message.contains("SYNTAX_ERR") ||
      message.contains("INVALID_EXPRESSION_ERR");
  }

  public InvalidSelectorException wrap(Throwable error) {
    return (error instanceof InvalidSelectorException) ?
      (InvalidSelectorException) error :
      new InvalidSelectorException("Invalid selector", error);
  }
}

@@ -248,16 +248,48 @@
 Default;
+%0Aimport java.util.regex.Pattern;
 %0A%0Aimport
@@ -329,16 +329,62 @@
 NonNull;
+%0Aimport static java.util.regex.Pattern.DOTALL;
 %0A%0A@Param
@@ -431,16 +431,352 @@
 eanup %7B%0A
+  private static final Pattern REGEX_FIRST_LINE = Pattern.compile(%22(%5B%5E%5C%5Cn%5D*)%5C%5Cn.*%22, DOTALL);%0A  private static final Pattern REGEX_SELENIUM_WARNING = Pattern.compile(%22(.*)%5C%5C(WARNING: The server did not provide any stacktrace.*%22);%0A  private static final Pattern REGEX_SELENIUM_PACKAGE = Pattern.compile(%22org%5C%5C.openqa%5C%5C.selenium%5C%5C.(.*)%22);%0A
   public
@@ -1128,23 +1128,20 @@
 ) %7B%0A    
-return 
+if (
 webDrive
@@ -1166,344 +1166,543 @@
 null
- %7C%7C webDriverExceptionInfo.indexOf('%5Cn') == -1 ?%0A      webDriverExceptionInfo :%0A      webDriverExceptionInfo%0A        .substring(0, webDriverExceptionInfo.indexOf('%5Cn'))%0A        .replaceFirst(%22(.*)%5C%5C(WARNING: The server did not provide any stacktrace.*%22, 
+) return null;%0A%0A    return cleanupSeleniumPackage(cleanupSeleniumWarning(extractFirstLine(webDriverExceptionInfo))).trim();%0A  %7D%0A%0A  private String extractFirstLine(String text) %7B%0A    return REGEX_FIRST_LINE.matcher(text).replaceFirst(%22$1%22);%0A  %7D%0A%0A  private String cleanupSeleniumWarning(String firstLine) %7B%0A    return REGEX_SELENIUM_WARNING.matcher(firstLine).replaceFirst(
 %22$1%22)
+;
 %0A  
-      .replaceFirst(%22org%5C%5C.openqa%5C%5C.selenium%5C%5C.(.*)%22, %22$1%22)%0A        .trim(
+%7D%0A%0A  private String cleanupSeleniumPackage(String withoutSeleniumBloat) %7B%0A    return REGEX_SELENIUM_PACKAGE.matcher(withoutSeleniumBloat).replaceFirst(%22$1%22
 );%0A 

use pre-compiled regular expressions for performance