/*
 * Copyright (C) 2014 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.welcome.install;

import com.android.sdklib.SdkManager;
import com.android.sdklib.repository.descriptors.IPkgDesc;
import com.android.sdklib.repository.descriptors.PkgType;
import com.android.sdklib.repository.local.LocalPkgInfo;
import com.android.sdklib.repository.local.LocalSdk;
import com.android.tools.idea.sdk.remote.RemotePkgInfo;
import com.android.tools.idea.sdk.remote.UpdatablePkgInfo;
import com.android.tools.idea.sdk.SdkPackages;
import com.android.tools.idea.sdk.remote.internal.updater.SdkUpdaterNoWindow;
import com.android.utils.ILogger;
import com.android.utils.NullLogger;
import com.google.common.base.Function;
import com.google.common.collect.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * Installs SDK components.
 */
public final class ComponentInstaller {
  @Nullable private final Multimap<PkgType, RemotePkgInfo> myRemotePackages;

  public ComponentInstaller(@Nullable Multimap<PkgType, RemotePkgInfo> remotePackages) {
    myRemotePackages = remotePackages;
  }

  private static Set<String> getPackageIds(Iterable<LocalPkgInfo> localPackages) {
    Set<String> toUpdate = Sets.newHashSet();
    for (LocalPkgInfo localPkgInfo : localPackages) {
      toUpdate.add(localPkgInfo.getDesc().getInstallId());
    }
    return toUpdate;
  }

  private static List<LocalPkgInfo> getInstalledPackages(@NotNull SdkManager manager, @NotNull Set<String> toInstall) {
    LocalSdk localSdk = manager.getLocalSdk();
    LocalPkgInfo[] installed = localSdk.getPkgsInfos(EnumSet.allOf(PkgType.class));
    List<LocalPkgInfo> toCheckForUpdate = Lists.newArrayListWithCapacity(installed.length);
    for (LocalPkgInfo info : installed) {
      if (toInstall.contains(info.getDesc().getInstallId())) {
        toCheckForUpdate.add(info);
      }
    }
    return toCheckForUpdate;
  }

  private Iterable<LocalPkgInfo> getOldPackages(Collection<LocalPkgInfo> installed) {
    if (myRemotePackages != null) {
      LocalPkgInfo[] packagesArray = ArrayUtil.toObjectArray(installed, LocalPkgInfo.class);
      SdkPackages result = new SdkPackages(packagesArray, myRemotePackages);
      return Iterables.transform(result.getUpdatedPkgs(), new Function<UpdatablePkgInfo, LocalPkgInfo>() {
        @Override
        public LocalPkgInfo apply(@Nullable UpdatablePkgInfo input) {
          return input.getLocalInfo();
        }
      });
    }
    else {
      return installed; // We should try reinstalling all...
    }
  }

  private Set<String> getRequiredPackages(@NotNull Iterable<? extends InstallableComponent> components) {
    // TODO: Prompt about connection in handoff case?
    Set<String> packages = Sets.newHashSet();
    for (InstallableComponent component : components) {
      for (IPkgDesc pkg : component.getRequiredSdkPackages(myRemotePackages)) {
        if (pkg != null) {
          packages.add(pkg.getInstallId());
        }
      }
    }
    return packages;
  }

  /**
   * Returns a list of package install IDs for packages that are missing or outdated.
   *
   * @param manager SDK manager instance or <code>null</code> if this is a new install.
   * @param defaultUpdateAvailable If true, and if remote package information is not available, assume each package may have an update and
   *                               try to reinstall. If false and remote package information not available, assume no updates are available.
   */
  public ArrayList<String> getPackagesToInstall(@Nullable SdkManager manager, @NotNull Iterable<? extends InstallableComponent> components,
                                                boolean defaultUpdateAvailable) {
    Set<String> toInstall = getRequiredPackages(components);
    if (manager == null) {
      return Lists.newArrayList(toInstall);
    }
    else {
      List<LocalPkgInfo> installed = getInstalledPackages(manager, toInstall);
      if (!installed.isEmpty()) {
        toInstall.removeAll(getPackageIds(installed));
        if (myRemotePackages != null || defaultUpdateAvailable) {
          toInstall.addAll(getPackageIds(getOldPackages(installed)));
        }
      }
      return Lists.newArrayList(toInstall);
    }
  }

  /**
   * Returns a collection of package info objects for packages that will be installed.
   */
  public Collection<RemotePkgInfo> getPackagesToInstallInfos(@Nullable String sdkPath,
                                                             @NotNull Iterable<? extends InstallableComponent> components) {
    if (!StringUtil.isEmptyOrSpaces(sdkPath) && myRemotePackages != null) {
      SdkManager sdkManager = SdkManager.createManager(sdkPath, new NullLogger());
      if (sdkManager != null) {
        Set<String> packagesToInstall = ImmutableSet
          .copyOf(new ComponentInstaller(myRemotePackages).getPackagesToInstall(sdkManager, components, true));
        Set<RemotePkgInfo> remotePackages = Sets.newHashSetWithExpectedSize(packagesToInstall.size());
        for (RemotePkgInfo remotePkgInfo : myRemotePackages.values()) {
          if (packagesToInstall.contains(remotePkgInfo.getPkgDesc().getInstallId())) {
            remotePackages.add(remotePkgInfo);
          }
        }
        return remotePackages;
      }
    }
    return ImmutableSet.of();
  }

  public void installPackages(@NotNull SdkManager manager, @NotNull ArrayList<String> packages, ILogger logger) throws WizardException {
    SdkUpdaterNoWindow updater = new SdkUpdaterNoWindow(manager.getLocation(), manager, logger, false, true, null, null);
    updater.updateAll(packages, true, false, null, false);
  }
}
