// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you 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 org.openqa.selenium.testing.drivers;

import static org.openqa.selenium.build.DevMode.isInDevMode;

import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.BrowserType;
import org.openqa.selenium.safari.SafariDriver;

import java.lang.reflect.InvocationTargetException;
import java.util.function.Supplier;

public class DefaultDriverSupplier implements Supplier<WebDriver> {

  private Supplier<WebDriver> driverSupplier;

  public DefaultDriverSupplier(Capabilities capabilities) {
    String browserName = capabilities == null ? "" : capabilities.getBrowserName();

    if (BrowserType.CHROME.equals(browserName)) {
      driverSupplier = () -> new TestChromeDriver(capabilities);
    } else if (BrowserType.OPERA_BLINK.equals(browserName)) {
      driverSupplier = () -> new TestOperaBlinkDriver(capabilities);
    } else if (BrowserType.FIREFOX.equals(browserName)) {
      if (isInDevMode() && ((FirefoxOptions) capabilities).isLegacy()) {
        driverSupplier = () -> new SynthesizedFirefoxDriver(capabilities);
      } else {
        driverSupplier = () -> new FirefoxDriver(capabilities);
      }
    } else if (BrowserType.HTMLUNIT.equals(browserName)) {
      driverSupplier = () -> new HtmlUnitDriver(capabilities);
    } else if (BrowserType.IE.equals(browserName)) {
      driverSupplier = () -> new InternetExplorerDriver(capabilities);
    } else if (browserName.toLowerCase().contains(BrowserType.SAFARI)) {
      driverSupplier = () -> new SafariDriver(capabilities);
    } else if (System.getProperty("selenium.browser.class_name") != null) {
      // No browser name specified, let's try reflection
      String className = System.getProperty("selenium.browser.class_name");
      driverSupplier = () -> {
        try {
          Class<? extends WebDriver> driverClass = Class.forName(className).asSubclass(WebDriver.class);
          return driverClass.getConstructor(Capabilities.class).newInstance(capabilities);
        } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
          throw new RuntimeException(e);
        }
      };
    } else {
      if (isInDevMode()) {
        driverSupplier = () -> new SynthesizedFirefoxDriver(capabilities);
      } else {
        throw new RuntimeException("No driver can be provided for capabilities " + capabilities);
      }
    }
  }

  public WebDriver get() {
    return driverSupplier.get();
  }
}

@@ -854,15 +854,8 @@
 ort 
-static 
 org.
@@ -874,35 +874,21 @@
 ium.
-build.DevMode.isInDevMode;%0A
+Capabilities;
 %0Aimp
@@ -903,32 +903,41 @@
 openqa.selenium.
+Immutable
 Capabilities;%0Aim
@@ -1026,59 +1026,8 @@
 er;%0A
-import org.openqa.selenium.firefox.FirefoxOptions;%0A
 impo
@@ -1228,60 +1228,8 @@
 r;%0A%0A
-import java.lang.reflect.InvocationTargetException;%0A
 impo
@@ -1830,83 +1830,8 @@
 ) %7B%0A
-      if (isInDevMode() && ((FirefoxOptions) capabilities).isLegacy()) %7B%0A  
     
@@ -1855,35 +1855,24 @@
 = () -%3E new 
-Synthesized
 FirefoxDrive
@@ -1892,95 +1892,8 @@
 s);%0A
-      %7D else %7B%0A        driverSupplier = () -%3E new FirefoxDriver(capabilities);%0A      %7D%0A
     
@@ -1991,24 +1991,88 @@
 lUnitDriver(
+%0A          capabilities == null ? new ImmutableCapabilities() : 
 capabilities
@@ -2803,330 +2803,115 @@
 ch (
-ClassNotFoundException %7C NoSuchMethodException %7C InvocationTargetException %7C InstantiationException %7C IllegalAccessException e) %7B%0A          throw new RuntimeException(e);%0A        %7D%0A      %7D;%0A    %7D else %7B%0A      if (isInDevMode()) %7B%0A        driverSupplier = () -%3E new SynthesizedFirefoxDriver(capabilities);%0A      %7D else %7B%0A  
+ReflectiveOperationException e) %7B%0A          throw new RuntimeException(e);%0A        %7D%0A      %7D;%0A    %7D else %7B%0A
     
@@ -3002,24 +3002,16 @@
 ities);%0A
-      %7D%0A
     %7D%0A  

Fix potential problems creating a test driver