/*
 * 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.run;

import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Utility methods for selecting a running device.
 */
public class DeviceSelectionUtils {
  @NotNull private static final Logger LOG = Logger.getInstance(DeviceSelectionUtils.class);
  // We remember what serials the user uses so we can pre-select them in the manual choosing dialog.
  @NonNls private static final String ANDROID_TARGET_DEVICES_PROPERTY = "AndroidTargetDevices";

  /**
   * Returns a compatible, already-running device for launch.
   * If no compatible devices are running, returns an empty list.
   * If exactly one compatible device is running, returns it.
   * If multiple compatible devices are running, prompt the user to select devices.
   * If they select any, return them, but if they do not, return null.
   */
  @Nullable
  public static Collection<IDevice> chooseRunningDevice(@NotNull final AndroidFacet facet,
                                                        @NotNull final Predicate<IDevice> deviceFilter,
                                                        @NotNull final DeviceCount deviceCount) {
    final Collection<IDevice> compatibleDevices = getAllCompatibleDevices(deviceFilter);

    if (compatibleDevices.isEmpty()) {
      return ImmutableList.of();
    }
    else if (compatibleDevices.size() == 1) {
      return compatibleDevices;
    }
    else {
      // Ask the user to pick one (or more) of the matching devices.
      final AtomicReference<IDevice[]> devicesRef = new AtomicReference<IDevice[]>();
      ApplicationManager.getApplication().invokeAndWait(new Runnable() {
        @Override
        public void run() {
          devicesRef.set(chooseDevicesManually(facet, deviceFilter, deviceCount));
        }
      });
      // Return the selected devices, or null if the user cancelled.
      return devicesRef.get().length > 0 ? ImmutableList.copyOf(devicesRef.get()) : null;
    }
  }

  @NotNull
  public static List<IDevice> getAllCompatibleDevices(Predicate<IDevice> deviceFilter) {
    final List<IDevice> compatibleDevices = new ArrayList<IDevice>();
    final AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();

    if (bridge != null) {
      IDevice[] devices = bridge.getDevices();

      for (IDevice device : devices) {
        if (deviceFilter.apply(device)) {
          compatibleDevices.add(device);
        }
      }
    }
    return compatibleDevices;
  }

  @NotNull
  public static Collection<IDevice> getOnlineDevices(@Nullable Collection<IDevice> devices) {
    if (devices == null) {
      return Collections.emptyList();
    }

    final List<IDevice> online = Lists.newArrayListWithExpectedSize(devices.size());
    for (IDevice device : devices) {
      if (device.isOnline()) {
        online.add(device);
      }
    }
    return online;
  }

  @NotNull
  private static IDevice[] chooseDevicesManually(@NotNull AndroidFacet facet,
                                                 @NotNull Predicate<IDevice> filter,
                                                 @NotNull DeviceCount deviceCount) {
    final Project project = facet.getModule().getProject();
    String value = PropertiesComponent.getInstance(project).getValue(ANDROID_TARGET_DEVICES_PROPERTY);
    String[] selectedSerials = value != null ? deserialize(value) : null;
    AndroidPlatform platform = AndroidPlatform.getInstance(facet.getModule());
    if (platform == null) {
      LOG.error("Android platform not set for module: " + facet.getModule().getName());
      return DeviceChooser.EMPTY_DEVICE_ARRAY;
    }
    DeviceChooserDialog chooser =
      new DeviceChooserDialog(facet, platform.getTarget(), deviceCount.isMultiple(), selectedSerials, filter);
    chooser.show();
    IDevice[] devices = chooser.getSelectedDevices();
    if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE || devices.length == 0) {
      return DeviceChooser.EMPTY_DEVICE_ARRAY;
    }
    PropertiesComponent.getInstance(project).setValue(ANDROID_TARGET_DEVICES_PROPERTY, serialize(devices));
    return devices;
  }

  @NotNull
  public static String serialize(@NotNull IDevice[] devices) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0, n = devices.length; i < n; i++) {
      builder.append(devices[i].getSerialNumber());
      if (i < n - 1) {
        builder.append(' ');
      }
    }
    return builder.toString();
  }

  @NotNull
  private static String[] deserialize(@NotNull String s) {
    return s.split(" ");
  }
}
