/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.cli;

import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.MultiLineReceiver;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.TriState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

import javax.annotation.Nullable;

/**
 * Base class for commands that use the AndroidDebugBridge to run commands on devices.
 * Currently, {@link InstallCommand}, {@link UninstallCommand}.
 *
 * @param <T>
 */
public abstract class AdbCommandRunner<T extends AbstractCommandOptions>
    extends AbstractCommandRunner<T> {

  private static final long ADB_CONNECT_TIMEOUT_MS = 5000;
  private static final long ADB_CONNECT_TIME_STEP_MS = ADB_CONNECT_TIMEOUT_MS / 10;

  // Taken from ddms source code.
  final static int INSTALL_TIMEOUT = 2*60*1000; // 2 min

  protected AdbCommandRunner(CommandRunnerParams params) {
    super(params);
  }

  /**
   * Returns list of devices that pass the filter. If there is an invalid combination or no
   * devices are left after filtering this function prints an error and returns null.
   */
  @Nullable
  @VisibleForTesting
  List<IDevice> filterDevices(IDevice[] allDevices,
                              AdbOptions adbOptions,
                              TargetDeviceOptions deviceOptions) {
    if (allDevices.length == 0) {
      console.printBuildFailure("No devices are found.");
      return null;
    }

    List<IDevice> devices = Lists.newArrayList();
    TriState emulatorsOnly = TriState.UNSPECIFIED;
    if (deviceOptions.isEmulatorsOnlyModeEnabled() && adbOptions.isMultiInstallModeEnabled()) {
      emulatorsOnly = TriState.UNSPECIFIED;
    } else if (deviceOptions.isEmulatorsOnlyModeEnabled()) {
      emulatorsOnly = TriState.TRUE;
    } else if (deviceOptions.isRealDevicesOnlyModeEnabled()) {
      emulatorsOnly = TriState.FALSE;
    }

    int onlineDevices = 0;
    for (IDevice device : allDevices) {
      boolean passed = false;
      if (device.isOnline()) {
        onlineDevices++;

        boolean serialMatches = true;
        if (deviceOptions.hasSerialNumber()) {
          serialMatches = device.getSerialNumber().equals(deviceOptions.getSerialNumber());
        }

        boolean deviceTypeMatches;
        if (emulatorsOnly.isSet()) {
          // Only devices of specific type are accepted:
          // either real devices only or emulators only.
          deviceTypeMatches = (emulatorsOnly.asBoolean() == device.isEmulator());
        } else {
          // All online devices match.
          deviceTypeMatches = true;
        }
        passed = serialMatches && deviceTypeMatches;
      }

      if (passed) {
        devices.add(device);
      }
    }

    // Filtered out all devices.
    if (onlineDevices == 0) {
      console.printBuildFailure("No devices are found.");
      return null;
    }

    if (devices.isEmpty()) {
      console.printBuildFailure(String.format(
          "Found %d connected device(s), but none of them matches specified filter.", onlineDevices
      ));
      return null;
    }

    // Found multiple devices but multi-install mode is not enabled.
    if (!adbOptions.isMultiInstallModeEnabled() && devices.size() > 1) {
      console.printBuildFailure(
          String.format("%d device(s) matches specified device filter (1 expected).\n" +
                        "Either disconnect other devices or enable multi-install mode (%s).",
                         devices.size(), AdbOptions.MULTI_INSTALL_MODE_SHORT_ARG));
      return null;
    }

    // Report if multiple devices are matching the filter.
    if (devices.size() > 1) {
      console.getStdOut().printf("Found " + devices.size() + " matching devices.\n");
    }
    return devices;
  }

  @VisibleForTesting
  boolean isAdbInitialized(AndroidDebugBridge adb) {
    return adb.isConnected() && adb.hasInitialDeviceList();
  }

  /**
   * Creates connection to adb and waits for this connection to be initialized
   * and receive initial list of devices.
   */
  @VisibleForTesting
  @Nullable
  @SuppressWarnings("PMD.EmptyCatchBlock")
  AndroidDebugBridge createAdb(ExecutionContext context) {
    try {
      AndroidDebugBridge.init(/* clientSupport */ false);
    } catch (IllegalStateException ex) {
      // ADB was already initialized, we're fine, so just ignore.
    }

    AndroidDebugBridge adb = null;
    if (context != null) {
      adb = AndroidDebugBridge.createBridge(context.getPathToAdbExecutable(), false);
    } else {
      adb = AndroidDebugBridge.createBridge();
    }
    if (adb == null) {
      console.printBuildFailure("Failed to connect to adb. Make sure adb server is running.");
      return null;
    }

    long start = System.currentTimeMillis();
    while (!isAdbInitialized(adb)) {
      long timeLeft = start + ADB_CONNECT_TIMEOUT_MS - System.currentTimeMillis();
      if (timeLeft <= 0) {
        break;
      }
      try {
        Thread.sleep(ADB_CONNECT_TIME_STEP_MS);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
        break;
      }
    }
    return isAdbInitialized(adb) ? adb : null;
  }

  /**
   * Execute an {@link AdbCallable} for all matching devices. This functions performs device
   * filtering based on three possible arguments:
   *
   *  -e (emulator-only) - only emulators are passing the filter
   *  -d (device-only) - only real devices are passing the filter
   *  -s (serial) - only device/emulator with specific serial number are passing the filter
   *
   *  If more than one device matches the filter this function will fail unless multi-install
   *  mode is enabled (-x). This flag is used as a marker that user understands that multiple
   *  devices will be used to install the apk if needed.
   */
  @VisibleForTesting
  protected boolean adbCall(AdbOptions options,
                            TargetDeviceOptions deviceOptions,
                            ExecutionContext context,
                            AdbCallable adbCallable) {

    // Initialize adb connection.
    AndroidDebugBridge adb = createAdb(context);
    if (adb == null) {
      console.printBuildFailure("Failed to create adb connection.");
      return false;
    }

    // Build list of matching devices.
    List<IDevice> devices = filterDevices(adb.getDevices(), options, deviceOptions);
    if (devices == null) {
      return false;
    }

    int adbThreadCount = options.getAdbThreadCount();
    if (adbThreadCount <= 0) {
      adbThreadCount = devices.size();
    }

    // Start executions on all matching devices.
    List<ListenableFuture<Boolean>> futures = Lists.newArrayList();
    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
        Executors.newFixedThreadPool(adbThreadCount));

    for (final IDevice device : devices) {
      futures.add(executorService.submit(adbCallable.forDevice(device)));
    }

    // Wait for all executions to complete or fail.
    List<Boolean> results = null;
    try {
      results = Futures.allAsList(futures).get();
    } catch (ExecutionException ex) {
      console.printBuildFailure("Failed: " + adbCallable);
      ex.printStackTrace(console.getStdErr());
      return false;
    } catch (InterruptedException ex) {
      console.printBuildFailure("Interrupted.");
      ex.printStackTrace(console.getStdErr());
      return false;
    } finally {
      executorService.shutdownNow();
    }

    int successCount = 0;
    for (Boolean result : results) {
      if (result) {
        successCount++;
      }
    }
    int failureCount = results.size() - successCount;

    // Report results.
    if (successCount > 0) {
      console.printSuccess(
          String.format("Succesfully ran %s on %d device(s)", adbCallable, successCount));
    }
    if (failureCount > 0) {
      console.printBuildFailure(
          String.format("Failed to %s on %d device(s).", adbCallable, failureCount));
    }

    return failureCount == 0;
  }

  /**
   * Base class for commands to be run against an {@link com.android.ddmlib.IDevice IDevice}.
   */
  public abstract class AdbCallable {

    /**
     * Perform the actions specified by this {@code AdbCallable} and return true on success.
     * @param device the {@link com.android.ddmlib.IDevice IDevice} to run against
     * @return {@code true} if the command succeeded.
     */
    public abstract boolean call(IDevice device) throws Exception;

    /**
     * Wraps this as a {@link java.util.concurrent.Callable Callable&lt;Boolean&gt;} whose
     * {@link Callable#call() call()} method calls
     * {@link AdbCommandRunner.AdbCallable#call(IDevice) call(IDevice)} against the specified
     * device.
     * @param device the {@link com.android.ddmlib.IDevice IDevice} to run against.
     * @return a {@code Callable}
     */
    public Callable<Boolean> forDevice(final IDevice device) {
      return new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
          return AdbCallable.this.call(device);
        }
        @Override
        public String toString() {
          return AdbCallable.this.toString();
        }
      };
    }
  }

  /**
   * Implementation of {@link com.android.ddmlib.IShellOutputReceiver} with helper functions to
   * parse output lines and figure out if a call to
   * {@link com.android.ddmlib.IDevice#executeShellCommand(String,
   * com.android.ddmlib.IShellOutputReceiver)} succeeded.
   */
  protected static abstract class ErrorParsingReceiver extends MultiLineReceiver {

    private String errorMessage = null;

    /**
     * Look for an error message in {@code line}.
     * @param line
     * @return an error message if {@code line} is indicative of an error, {@code null} otherwise.
     */
    protected abstract String matchForError(String line);

    /**
     * Look for a message indicating success - the error message is reset if this returns
     * {@code true}.
     * @param line
     * @return {@code true} if this line indicates success.
     */
    protected boolean matchForSuccess(String line) {
      return false;
    }

    @Override
    public void processNewLines(String[] lines) {
        for (String line : lines) {
            if (line.length() > 0) {
                if (matchForSuccess(line)) {
                    errorMessage = null;
                } else {
                    String err = matchForError(line);
                    if (err != null) {
                      errorMessage = err;
                    }
                }
            }
        }
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    public String getErrorMessage() {
       return errorMessage;
    }
  }

}
