/*
 * 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.getPackages().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();
  }
}
