public void Run(InstallOptions opts)
        {
            BackwardCompatibility.RemoveOldConfigFileIfItExists(_fs);
            var config = InstallationValidator.VerifyInstallation(_fs, _configLoader.GetCurrentConfig(), _progress);

            try
            {
                Install(config, opts);
            }
            finally
            {
                // Save config
                _configLoader.Save(config);
            }
        }
        void Install(OptionalSdkConfigOptions config, InstallOptions opts)
        {
            // Remove old NDK installation
            config.AndroidNdkDirectory.Do(ndkPath => BackwardCompatibility.RemoveOldNdk(_fs, ndkPath));

            if (config.JavaJdkDirectory.HasValue == false)
            {
                var javaValidator = new JavaValidator(_fs);
                config.JavaJdkDirectory = TryToFindJdk(_fs, javaValidator, _progress)
                                          .Or(() => opts.Noninteractive ? Optional.None() : AskUserToProvidePath("Java Development Kit", javaValidator, _progress));
            }

            if (config.AndroidSdkDirectory.HasValue == false)
            {
                var androidSdkValidator = new AndroidSDKValidator(_fs);
                config.AndroidSdkDirectory = TryToFindAndroidSdk(androidSdkValidator, _progress)
                                             .Or(() => opts.Noninteractive ? Optional.None() : AskUserToProvidePath("Android SDK", androidSdkValidator, _progress));
            }

            // Then install based on configuration
            config.JavaJdkDirectory = config.JavaJdkDirectory.MatchWith(
                _ => _,
                () =>
            {
                var defaultPath = Platform.OperatingSystem == OS.Windows
                                                ? PathExtensions.GetEnvironmentPath(Environment.SpecialFolder.ProgramFiles)
                                  / new DirectoryName("Java")
                                  / new DirectoryName("jdk1.8.0_40")
                                                : AbsoluteDirectoryPath.Parse("/Library/Java/JavaVirtualMachines")
                                  / new DirectoryName("jdk1.8.0_40.jdk")
                                  / new DirectoryName("Contents")
                                  / new DirectoryName("Home");

                var installer = new JavaInstaller(_fs);
                installer.Install(CancellationToken.None, _dialog, _progress, opts);
                return(defaultPath);
            });

            config.JavaJdkDirectory.Do(jdk => Environment.SetEnvironmentVariable("JAVA_HOME", jdk.NativePath, EnvironmentVariableTarget.Process));

            config.AndroidSdkDirectory = config.AndroidSdkDirectory.MatchWith(
                _ => _,
                () =>
            {
                var defaultPath = Platform.OperatingSystem == OS.Mac
                                                ? PathExtensions.GetEnvironmentPath(Environment.SpecialFolder.Personal)
                                  / new DirectoryName("Library")
                                  / new DirectoryName("Android")
                                  / new DirectoryName("sdk")
                                                : PathExtensions.GetEnvironmentPath(Environment.SpecialFolder.LocalApplicationData)
                                  / new DirectoryName("Fusetools")
                                  / new DirectoryName("Fuse")
                                  / new DirectoryName("Android")
                                  / new DirectoryName("AndroidSDK");

                var installer = new AndroidSDKInstaller(defaultPath, _fs);
                installer.Install(CancellationToken.None, _dialog, _progress, opts);
                return(defaultPath);
            });

            config.AndroidSdkDirectory.Do(
                androidRoot =>
            {
                if (config.HaveAllSdkPackages &&
                    config.AndroidNdkDirectory.HasValue)
                {
                    return;
                }

                var installer = new AndroidSDKPackageInstaller(
                    _fs,
                    androidRoot,
                    Platform.OperatingSystem == OS.Windows
                                                        ? androidRoot / new DirectoryName("tools") / new FileName("android.bat")
                                                        : androidRoot / new DirectoryName("tools") / new FileName("android"),
                    Platform.OperatingSystem == OS.Windows
                                                        ? androidRoot / new DirectoryName("tools") / new DirectoryName("bin") / new FileName("sdkmanager.bat")
                                                        : androidRoot / new DirectoryName("tools") / new DirectoryName("bin") / new FileName("sdkmanager"));

                var result = installer.Install(CancellationToken.None, _dialog, _progress);

                config.AndroidNdkDirectory = result.NdkBundle;
            });
        }