/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed 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 com.android.tools.idea.sdk.remote.internal.updater;

import com.android.annotations.NonNull;
import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.repository.ISdkChangeListener;
import com.android.sdklib.repository.License;
import com.android.sdklib.repository.SdkRepoConstants;
import com.android.sdklib.util.LineUtil;
import com.android.tools.idea.sdk.SdkState;
import com.android.tools.idea.sdk.remote.RemotePkgInfo;
import com.android.tools.idea.sdk.remote.internal.*;
import com.android.tools.idea.sdk.remote.internal.archives.Archive;
import com.android.tools.idea.sdk.remote.internal.archives.ArchiveInstaller;
import com.android.tools.idea.sdk.remote.internal.packages.RemoteAddonPkgInfo;
import com.android.tools.idea.sdk.remote.internal.packages.PlatformToolRemotePkgInfo;
import com.android.tools.idea.sdk.remote.internal.packages.RemoteToolPkgInfo;
import com.android.tools.idea.sdk.remote.internal.sources.SdkRepoSource;
import com.android.tools.idea.sdk.remote.internal.sources.SdkSourceCategory;
import com.android.tools.idea.sdk.remote.internal.sources.SdkSources;
import com.android.utils.ILogger;
import com.android.utils.IReaderLogger;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.android.sdk.AndroidSdkUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;

/**
 * Data shared by the SDK Manager updaters.
 */
public class UpdaterData implements IUpdaterData {

  public static final int NO_TOOLS_MSG = 0;
  public static final int TOOLS_MSG_UPDATED_FROM_ADT = 1;
  public static final int TOOLS_MSG_UPDATED_FROM_SDKMAN = 2;

  private String mOsSdkRoot;

  /**
   * Holds all sources. Do not use this directly.
   * Instead use {@link #getSources()} so that unit tests can override this as needed.
   */
  private final SdkSources mSources = new SdkSources();
  /**
   * Holds settings. Do not use this directly.
   * Instead use {@link #getSettingsController()} so that unit tests can override this.
   */
  private final SettingsController mSettingsController;
  private final ArrayList<ISdkChangeListener> mListeners = new ArrayList<ISdkChangeListener>();
  private final ILogger mSdkLog;
  private ITaskFactory mTaskFactory;

  private SdkManager mSdkManager;
  /**
   * The current {@link DownloadCache} to use.
   * Lazily created in {@link #getDownloadCache()}.
   */
  private DownloadCache mDownloadCache;

  /**
   * Creates a new updater data.
   *
   * @param sdkLog    Logger. Cannot be null.
   * @param osSdkRoot The OS path to the SDK root.
   */
  public UpdaterData(String osSdkRoot, ILogger sdkLog) {
    mOsSdkRoot = osSdkRoot;
    mSdkLog = sdkLog;

    mSettingsController = initSettingsController();
    initSdk();
  }

  // ----- getters, setters ----

  public String getOsSdkRoot() {
    return mOsSdkRoot;
  }

  @Override
  public DownloadCache getDownloadCache() {
    if (mDownloadCache == null) {
      mDownloadCache = new DownloadCache(
        getSettingsController().getSettings().getUseDownloadCache() ? DownloadCache.Strategy.FRESH_CACHE : DownloadCache.Strategy.DIRECT);
    }
    return mDownloadCache;
  }

  public void setTaskFactory(ITaskFactory taskFactory) {
    mTaskFactory = taskFactory;
  }

  @Override
  public ITaskFactory getTaskFactory() {
    return mTaskFactory;
  }

  public SdkSources getSources() {
    return mSources;
  }

  @Override
  public ILogger getSdkLog() {
    return mSdkLog;
  }

  @Override
  public SdkManager getSdkManager() {
    return mSdkManager;
  }

  @Override
  public SettingsController getSettingsController() {
    return mSettingsController;
  }

  /**
   * Removes a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded.
   */
  public void removeListener(ISdkChangeListener listener) {
    mListeners.remove(listener);
  }

  protected void displayInitError(String error) {
    mSdkLog.error(null /* Throwable */, "%s", error);  //$NON-NLS-1$
  }

  // -----

  /**
   * Runs a runnable on the UI thread.
   * The base implementation just runs the runnable right away.
   *
   * @param r Non-null runnable.
   */
  protected void runOnUiThread(@NonNull Runnable r) {
    r.run();
  }

  /**
   * Initializes the {@link SdkManager} and the {@link AvdManager}.
   * Extracted so that we can override this in unit tests.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected void initSdk() {
    setSdkManager(SdkManager.createManager(mOsSdkRoot, mSdkLog));
    // notify listeners.
    broadcastOnSdkReload();
  }

  /**
   * Initializes the {@link SettingsController}
   * Extracted so that we can override this in unit tests.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected SettingsController initSettingsController() {
    SettingsController settingsController = new SettingsController(mSdkLog);
    return settingsController;
  }

  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected void setSdkManager(SdkManager sdkManager) {
    mSdkManager = sdkManager;
  }

  /**
   * Reloads the SDK content (targets).
   * <p/>
   * This also reloads the AVDs in case their status changed.
   * <p/>
   * This does not notify the listeners ({@link ISdkChangeListener}).
   */
  public void reloadSdk() {
    // reload SDK
    mSdkManager.reloadSdk(mSdkLog);

    // notify listeners
    broadcastOnSdkReload();
  }

  /**
   * Sets up the default sources: <br/>
   * - the default google SDK repository, <br/>
   * - the user sources from prefs <br/>
   * - the extra repo URLs from the environment, <br/>
   * - and finally the extra user repo URLs from the environment.
   */
  public void setupDefaultSources() {
    SdkSources sources = getSources();

    // Load the conventional sources.
    // For testing, the env var can be set to replace the default root download URL.
    // It must end with a / and its the location where the updater will look for
    // the repository.xml, addons_list.xml and such files.

    String baseUrl = System.getenv("SDK_TEST_BASE_URL");                        //$NON-NLS-1$
    if (baseUrl == null || baseUrl.length() <= 0 || !baseUrl.endsWith("/")) {   //$NON-NLS-1$
      baseUrl = SdkRepoConstants.URL_GOOGLE_SDK_SITE;
    }

    sources.add(SdkSourceCategory.ANDROID_REPO, new SdkRepoSource(baseUrl, SdkSourceCategory.ANDROID_REPO.getUiName()));

    // Load user sources (this will also notify change listeners but this operation is
    // done early enough that there shouldn't be any anyway.)
    sources.loadUserAddons(getSdkLog());
  }

  /**
   * Install the list of given {@link Archive}s. This is invoked by the user selecting some
   * packages in the remote page and then clicking "install selected".
   *
   * @param archives The archives to install. Incompatible ones will be skipped.
   * @param flags    Optional flags for the installer, such as {@link #NO_TOOLS_MSG}.
   * @return A list of archives that have been installed. Can be empty but not null.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected List<Archive> installArchives(final List<ArchiveInfo> archives, final int flags) {
    if (mTaskFactory == null) {
      throw new IllegalArgumentException("Task Factory is null");
    }

    // this will accumulate all the packages installed.
    final List<Archive> newlyInstalledArchives = new ArrayList<Archive>();

    final boolean forceHttp = getSettingsController().getSettings().getForceHttp();

    // sort all archives based on their dependency level.
    Collections.sort(archives, new InstallOrderComparator());

    mTaskFactory.start("Installing Archives", new ITask() {
      @Override
      public void run(ITaskMonitor monitor) {

        final int progressPerArchive = 2 * ArchiveInstaller.NUM_MONITOR_INC;
        monitor.setProgressMax(1 + archives.size() * progressPerArchive);
        monitor.setDescription("Preparing to install archives");

        boolean installedAddon = false;
        boolean installedTools = false;
        boolean installedPlatformTools = false;
        boolean preInstallHookInvoked = false;

        int numInstalled = 0;
        nextArchive:
        for (ArchiveInfo ai : archives) {
          Archive archive = ai.getNewArchive();
          if (archive == null) {
            // This is not supposed to happen.
            continue nextArchive;
          }

          int nextProgress = monitor.getProgress() + progressPerArchive;
          try {
            if (monitor.isCancelRequested()) {
              break;
            }

            ArchiveInfo[] adeps = ai.getDependsOn();
            if (adeps != null) {
              for (ArchiveInfo adep : adeps) {
                Archive na = adep.getNewArchive();
                if (na == null) {
                  // This archive depends on a missing archive.
                  // We shouldn't get here.
                  // Skip it.
                  monitor.log("Skipping '%1$s'; it depends on a missing package.", archive.getParentPackage().getShortDescription());
                  continue nextArchive;
                }
              }
            }

            if (!preInstallHookInvoked) {
              preInstallHookInvoked = true;
              broadcastPreInstallHook();
            }

            ArchiveInstaller installer = createArchiveInstaler();
            if (installer.install(ai, mOsSdkRoot, forceHttp, mSdkManager, getDownloadCache(), monitor)) {
              // We installed this archive.
              newlyInstalledArchives.add(archive);
              numInstalled++;

              // Check if we successfully installed a platform-tool or add-on package.
              if (archive.getParentPackage() instanceof RemoteAddonPkgInfo) {
                installedAddon = true;
              }
              else if (archive.getParentPackage() instanceof RemoteToolPkgInfo) {
                installedTools = true;
              }
              else if (archive.getParentPackage() instanceof PlatformToolRemotePkgInfo) {
                installedPlatformTools = true;
              }
            }

          }
          catch (Throwable t) {
            // Display anything unexpected in the monitor.
            String msg = t.getMessage();
            if (msg != null) {
              msg = String.format("Unexpected Error installing '%1$s': %2$s: %3$s", archive.getParentPackage().getShortDescription(),
                                  t.getClass().getCanonicalName(), msg);
            }
            else {
              // no error info? get the stack call to display it
              // At least that'll give us a better bug report.
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              t.printStackTrace(new PrintStream(baos));

              msg = String
                .format("Unexpected Error installing '%1$s'\n%2$s", archive.getParentPackage().getShortDescription(), baos.toString());
            }

            monitor.log("%1$s", msg);      //$NON-NLS-1$
            mSdkLog.error(t, "%1$s", msg);      //$NON-NLS-1$
          }
          finally {

            // Always move the progress bar to the desired position.
            // This allows internal methods to not have to care in case
            // they abort early
            monitor.incProgress(nextProgress - monitor.getProgress());
          }
        }

        if (installedAddon) {
          // Update the USB vendor ids for adb
          try {
            mSdkManager.updateAdb();
            monitor.log("Updated ADB to support the USB devices declared in the SDK add-ons.");
          }
          catch (Exception e) {
            mSdkLog.error(e, "Update ADB failed");
            monitor.logError("failed to update adb to support the USB devices declared in the SDK add-ons.");
          }
        }

        if (preInstallHookInvoked) {
          broadcastPostInstallHook();
        }

        if (installedAddon || installedPlatformTools) {
          // We need to restart ADB. Actually since we don't know if it's even
          // running, maybe we should just kill it and not start it.
          // Note: it turns out even under Windows we don't need to kill adb
          // before updating the tools folder, as adb.exe is (surprisingly) not
          // locked.

          askForAdbRestart(monitor);
        }

        if (installedTools) {
          notifyToolsNeedsToBeRestarted(flags);
        }

        if (numInstalled == 0) {
          monitor.setDescription("Done. Nothing was installed.");
        }
        else {
          monitor.setDescription("Done. %1$d %2$s installed.", numInstalled, numInstalled == 1 ? "package" : "packages");

          //notify listeners something was installed, so that they can refresh
          reloadSdk();
        }
      }
    });

    return newlyInstalledArchives;
  }

  /**
   * A comparator to sort all the {@link ArchiveInfo} based on their
   * dependency level. This forces the installer to install first all packages
   * with no dependency, then those with one level of dependency, etc.
   */
  private static class InstallOrderComparator implements Comparator<ArchiveInfo> {

    private final Map<ArchiveInfo, Integer> mOrders = new HashMap<ArchiveInfo, Integer>();

    @Override
    public int compare(ArchiveInfo o1, ArchiveInfo o2) {
      int n1 = getDependencyOrder(o1);
      int n2 = getDependencyOrder(o2);

      return n1 - n2;
    }

    private int getDependencyOrder(ArchiveInfo ai) {
      if (ai == null) {
        return 0;
      }

      // reuse cached value, if any
      Integer cached = mOrders.get(ai);
      if (cached != null) {
        return cached.intValue();
      }

      ArchiveInfo[] deps = ai.getDependsOn();
      if (deps == null) {
        return 0;
      }

      // compute dependencies, recursively
      int n = deps.length;

      for (ArchiveInfo dep : deps) {
        n += getDependencyOrder(dep);
      }

      // cache it
      mOrders.put(ai, Integer.valueOf(n));

      return n;
    }

  }

  /**
   * Attempts to restart ADB.
   * <p/>
   * If the "ask before restart" setting is set (the default), prompt the user whether
   * now is a good time to restart ADB.
   */
  protected void askForAdbRestart(ITaskMonitor monitor) {
    // Restart ADB if we don't need to ask.
    if (!getSettingsController().getSettings().getAskBeforeAdbRestart()) {
      AdbWrapper adb = new AdbWrapper(getOsSdkRoot(), monitor);
      adb.stopAdb();
      adb.startAdb();
    }
  }

  protected void notifyToolsNeedsToBeRestarted(int flags) {

    String msg = null;
    if ((flags & TOOLS_MSG_UPDATED_FROM_ADT) == TOOLS_MSG_UPDATED_FROM_ADT) {
      msg = "The Android SDK and AVD Manager that you are currently using has been updated. " +
            "Please also run Eclipse > Help > Check for Updates to see if the Android " +
            "plug-in needs to be updated.";

    }
    else if ((flags & TOOLS_MSG_UPDATED_FROM_SDKMAN) == TOOLS_MSG_UPDATED_FROM_SDKMAN) {
      msg = "The Android SDK and AVD Manager that you are currently using has been updated. " +
            "It is recommended that you now close the manager window and re-open it. " +
            "If you use Eclipse, please run Help > Check for Updates to see if the Android " +
            "plug-in needs to be updated.";
    }
    else if ((flags & NO_TOOLS_MSG) == NO_TOOLS_MSG) {
      return;
    }
    mSdkLog.info("%s", msg);  //$NON-NLS-1$
  }

  /**
   * Tries to update all the *existing* local packages.
   * This version is intended to run without a GUI and
   * only outputs to the current {@link ILogger}.
   *
   * @param pkgFilter           A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()}
   *                            or package indexes to limit the packages we can update or install.
   *                            A null or empty list means to update everything possible.
   * @param includeAll          True to list and install all packages, including obsolete ones.
   * @param dryMode             True to check what would be updated/installed but do not actually
   *                            download or install anything.
   * @param acceptLicense       SDK licenses to automatically accept.
   * @param includeDependencies If true, also include any required dependencies
   * @return A list of archives that have been installed. Can be null if nothing was done.
   */
  public List<Archive> updateOrInstallAll_NoGUI(Collection<String> pkgFilter,
                                                boolean includeAll,
                                                boolean dryMode,
                                                String acceptLicense,
                                                boolean includeDependencies) {

    List<ArchiveInfo> archives = getRemoteArchives(includeAll);

    // Filter the selected archives to only keep the ones matching the filter
    if (pkgFilter != null && pkgFilter.size() > 0 && archives != null && archives.size() > 0) {
      // Prepare a map install-id => package instance
      HashSet<String> installIds = new HashSet<String>();
      for (ArchiveInfo ai : archives) {
        Archive a = ai.getNewArchive();
        if (a != null) {
          RemotePkgInfo p = a.getParentPackage();
          if (p != null) {
            String iid = p.installId().toLowerCase(Locale.US);
            if (iid.length() > 0 && !installIds.contains(iid)) {
              installIds.add(iid);
            }
          }
        }
      }

      // Now intersect this with the pkgFilter requested by the user, in order to
      // only keep the classes that the user wants to install.
      // We also create a set with the package indices requested by the user
      // and a set of install-ids requested by the user.

      Set<String> userFilteredInstallIds = new HashSet<String>();

      for (String iid : pkgFilter) {
        // The install-id is not case-sensitive.
        iid = iid.toLowerCase(Locale.US);

        if (installIds.contains(iid)) {
          userFilteredInstallIds.add(iid);

        }
        else {
          // This should not happen unless there's a mismatch in the package map.
          mSdkLog.error(null, "Ignoring unknown package filter '%1$s'", iid);
        }
      }

      // Now filter the remote archives list to keep:
      // - any package which class matches userFilteredClasses
      // - any package index which matches userFilteredIndices
      // - any package install id which matches userFilteredInstallIds

      for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) {
        boolean keep = false;
        ArchiveInfo ai = it.next();
        Archive a = ai.getNewArchive();
        if (a != null) {
          RemotePkgInfo p = a.getParentPackage();
          if (p != null) {
            if (userFilteredInstallIds.contains(p.installId().toLowerCase(Locale.US))) {
              keep = true;
            }
          }
        }

        if (!keep) {
          it.remove();
        }
      }

      if (archives.isEmpty()) {
        mSdkLog.info(LineUtil.reflowLine(
          "Warning: The package filter removed all packages. There is nothing to install.\nPlease consider trying to update again without a package filter.\n"));
        return null;
      }
    }

    if (archives != null && !archives.isEmpty()) {
      if (includeDependencies) {
        List<ArchiveInfo> dependencies = getDependencies(archives);
        if (!dependencies.isEmpty()) {
          List<ArchiveInfo> combined = Lists.newArrayList();
          combined.addAll(dependencies);
          combined.addAll(archives);
          archives = combined;
        }
      }
      if (dryMode) {
        mSdkLog.info("Packages selected for install:\n");
        for (ArchiveInfo ai : archives) {
          Archive a = ai.getNewArchive();
          if (a != null) {
            RemotePkgInfo p = a.getParentPackage();
            if (p != null) {
              mSdkLog.info("- %1$s\n", p.getShortDescription());
            }
          }
        }
        mSdkLog.info("\nDry mode is on so nothing is actually being installed.\n");
      }
      else {
        if (acceptLicense(archives, acceptLicense, 100 /* numRetries */)) {
          return installArchives(archives, NO_TOOLS_MSG);
        }
      }
    }
    else {
      mSdkLog.info("There is nothing to install or update.\n");
    }

    return null;
  }

  private List<ArchiveInfo> getRemoteArchives(boolean includeAll) {
    SdkState state = SdkState.getInstance(AndroidSdkUtils.tryToChooseAndroidSdk());
    state.loadSynchronously(SdkState.DEFAULT_EXPIRATION_PERIOD_MS, false, null, null, null, false);
    List<ArchiveInfo> result = Lists.newArrayList();
    for (RemotePkgInfo remote : state.getRemotePkgInfos().values()) {
      if (includeAll || !remote.isObsolete()) {
        for (Archive archive : remote.getArchives()) {
          if (archive.isCompatible()) {
            result.add(new ArchiveInfo(archive, null, null));
          }
        }
      }
    }
    return result;
  }

  /**
   * Computes the transitive dependencies of the given list of archives. This will only
   * include dependencies that also need to be installed, not satisfied dependencies.
   */
  private static List<ArchiveInfo> getDependencies(@NonNull List<ArchiveInfo> archives) {
    List<ArchiveInfo> dependencies = Lists.newArrayList();
    for (ArchiveInfo archive : archives) {
      addDependencies(dependencies, archive, Sets.<ArchiveInfo>newHashSet());
    }
    return dependencies;
  }

  private static void addDependencies(@NonNull List<ArchiveInfo> dependencies,
                                      @NonNull ArchiveInfo archive,
                                      @NonNull Set<ArchiveInfo> visited) {
    if (visited.contains(archive)) {
      return;
    }
    visited.add(archive);

    ArchiveInfo[] dependsOn = archive.getDependsOn();
    if (dependsOn != null) {
      for (ArchiveInfo dependency : dependsOn) {
        if (!dependencies.contains(dependency)) {
          dependencies.add(dependency);
          addDependencies(dependencies, dependency, visited);
        }
      }
    }
  }

  /**
   * Validates that all archive licenses are accepted.
   * <p/>
   * There are 2 cases: <br/>
   * - When {@code acceptLicenses} is given, the licenses specified are automatically
   * accepted and all those not specified are automatically rejected. <br/>
   * - When {@code acceptLicenses} is empty or null, licenses are collected and there's
   * an input prompt on StdOut to ask a yes/no question. To output, this uses the
   * current {@link #mSdkLog} which should be configured to send
   * {@link ILogger#info(String, Object...)} directly to {@link System#out}. <br/>
   * <p/>
   * Finally only accepted licenses are kept in the archive list.
   *
   * @param archives         The archives to validate.
   * @param acceptLicenseIds A comma-separated list of licenses ids already approved.
   * @param numRetries       The number of times the command-line will ask to accept a given
   *                         license when the input doesn't match the expected y/n/yes/no answer.
   *                         Use 0 for infinite. Useful for unit-tests. Once the number of retries
   *                         is reached, the license is assumed as rejected.
   * @return True if there are any archives left to install.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  boolean acceptLicense(List<ArchiveInfo> archives, String acceptLicenseIds, final int numRetries) {
    TreeSet<String> acceptedLids = new TreeSet<String>();
    if (acceptLicenseIds != null) {
      acceptedLids.addAll(Arrays.asList(acceptLicenseIds.split(",")));  //$NON-NLS-1$
    }
    boolean automated = !acceptedLids.isEmpty();

    TreeSet<String> rejectedLids = new TreeSet<String>();
    TreeMap<String, License> lidToAccept = new TreeMap<String, License>();
    TreeMap<String, List<String>> lidPkgNames = new TreeMap<String, List<String>>();

    // Find the licenses needed. Include those already accepted.
    for (ArchiveInfo ai : archives) {
      License lic = getArchiveInfoLicense(ai);
      if (lic == null) {
        continue;
      }
      String lid = getLicenseId(lic);
      if (!acceptedLids.contains(lid)) {
        if (automated) {
          // Automatically reject those not already accepted
          rejectedLids.add(lid);
        }
        else {
          // Queue it to ask for it to be accepted
          lidToAccept.put(lid, lic);
          List<String> list = lidPkgNames.get(lid);
          if (list == null) {
            list = new ArrayList<String>();
            lidPkgNames.put(lid, list);
          }
          list.add(ai.getShortDescription());
        }
      }
    }

    // Ask for each license that needs to be asked manually for confirmation
    nextEntry:
    for (Map.Entry<String, License> entry : lidToAccept.entrySet()) {
      String lid = entry.getKey();
      License lic = entry.getValue();
      mSdkLog.info("-------------------------------\n");
      mSdkLog.info("License id: %1$s\n", lid);
      mSdkLog.info("Used by: \n - %1$s\n", Joiner.on("\n  - ").skipNulls().join(lidPkgNames.get(lid)));
      mSdkLog.info("-------------------------------\n\n");
      mSdkLog.info("%1$s\n", lic.getLicense());

      int retries = numRetries;
      tryAgain:
      while (true) {
        try {
          mSdkLog.info("Do you accept the license '%1$s' [y/n]: ", lid);

          byte[] buffer = new byte[256];
          if (mSdkLog instanceof IReaderLogger) {
            ((IReaderLogger)mSdkLog).readLine(buffer);
          }
          else {
            System.in.read(buffer);
          }
          mSdkLog.info("\n");

          String reply = new String(buffer, Charsets.UTF_8);
          reply = reply.trim().toLowerCase(Locale.US);

          if ("y".equals(reply) || "yes".equals(reply)) {
            acceptedLids.add(lid);
            continue nextEntry;

          }
          else if ("n".equals(reply) || "no".equals(reply)) {
            break tryAgain;

          }
          else {
            mSdkLog.info("Unknown response '%1$s'.\n", reply);
            if (--retries == 0) {
              mSdkLog.info("Max number of retries exceeded. Rejecting '%1$s'\n", lid);
              break tryAgain;
            }
            continue tryAgain;
          }

        }
        catch (IOException e) {
          // Panic. Don't install anything.
          e.printStackTrace();
          return false;
        }
      }
      rejectedLids.add(lid);
    }

    // Finally remove all archive which license is rejected or not accepted.
    for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) {
      ArchiveInfo ai = it.next();
      License lic = getArchiveInfoLicense(ai);
      if (lic == null) {
        continue;
      }
      String lid = getLicenseId(lic);
      if (rejectedLids.contains(lid) || !acceptedLids.contains(lid)) {
        mSdkLog.info("Package %1$s not installed due to rejected license '%2$s'.\n", ai.getShortDescription(), lid);
        it.remove();
      }
    }


    return !archives.isEmpty();
  }

  private License getArchiveInfoLicense(ArchiveInfo ai) {
    Archive a = ai.getNewArchive();
    if (a != null) {
      RemotePkgInfo p = a.getParentPackage();
      if (p != null) {
        License lic = p.getLicense();
        if (lic != null &&
            lic.getLicenseRef() != null &&
            lic.getLicense().length() > 0 &&
            lic.getLicense() != null &&
            lic.getLicense().length() > 0) {
          return lic;
        }
      }
    }

    return null;
  }

  private String getLicenseId(License lic) {
    return String.format("%1$s-%2$08x",       //$NON-NLS-1$
                         lic.getLicenseRef(), lic.getLicense().hashCode());
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#onSdkReload()}.
   * This can be called from any thread.
   */
  private void broadcastOnSdkReload() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.onSdkReload();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#preInstallHook()}.
   * This can be called from any thread.
   */
  private void broadcastPreInstallHook() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.preInstallHook();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#postInstallHook()}.
   * This can be called from any thread.
   */
  private void broadcastPostInstallHook() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.postInstallHook();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Internal helper to return a new {@link ArchiveInstaller}.
   * This allows us to override the installer for unit-testing.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected ArchiveInstaller createArchiveInstaler() {
    return new ArchiveInstaller();
  }
}
