// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.starlarkdebug.server;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.DebugEvent;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.DebugRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/** A basic implementation of a Starlark debugging client, for use in integration tests. */
class MockDebugClient {

  private static final int RESPONSE_TIMEOUT_MILLIS = 10000;
  private static final ExecutorService readTaskExecutor = Executors.newFixedThreadPool(1);

  private Socket clientSocket;

  final List<DebugEvent> unnumberedEvents = new ArrayList<>();
  final Map<Long, DebugEvent> responses = new HashMap<>();

  private Future<?> readTask;

  /** Connects to the debug server, and starts listening for events. */
  void connect(InetAddress addr, int port, Duration timeout) {
    long startTimeMillis = System.currentTimeMillis();
    IOException exception = null;
    while (System.currentTimeMillis() - startTimeMillis < timeout.toMillis()) {
      try {
        clientSocket = new Socket();
        clientSocket.connect(new InetSocketAddress(addr, port), 100);
        readTask =
            readTaskExecutor.submit(
                () -> {
                  while (true) {
                    eventReceived(DebugEvent.parseDelimitedFrom(clientSocket.getInputStream()));
                  }
                });
        return;
      } catch (IOException e) {
        exception = e;
      }
    }
    throw new RuntimeException("Couldn't connect to the debug server", exception);
  }

  void close() throws IOException {
    if (clientSocket != null) {
      clientSocket.close();
    }
    if (readTask != null) {
      readTask.cancel(true);
    }
  }

  /**
   * Blocks waiting for an unnumbered event (not a direct response to a request). Returns null if no
   * event arrives before the timeout.
   */
  @Nullable
  DebugEvent waitForEvent(Predicate<DebugEvent> predicate, Duration timeout) {
    waitForEvents(list -> list.stream().anyMatch(predicate), timeout);
    return unnumberedEvents.stream().filter(predicate).findFirst().orElse(null);
  }

  /**
   * Blocks waiting for a condition on all unnumbered events to be satisfied. Returns true if the
   * condition was satisfied before the timeout.
   */
  boolean waitForEvents(Predicate<List<DebugEvent>> predicate, Duration timeout) {
    long startTime = System.currentTimeMillis();
    synchronized (unnumberedEvents) {
      while (!predicate.test(ImmutableList.copyOf(unnumberedEvents))
          && System.currentTimeMillis() - startTime < timeout.toMillis()) {
        try {
          unnumberedEvents.wait(timeout.toMillis());
        } catch (InterruptedException e) {
          throw new AssertionError(e);
        }
      }
    }
    return predicate.test(ImmutableList.copyOf(unnumberedEvents));
  }

  /**
   * Sends a {@link DebugRequest} to the server, and blocks waiting for a response.
   *
   * @return the {@link DebugEvent} response from the server, or null if no response was received.
   */
  @Nullable
  DebugEvent sendRequestAndWaitForResponse(DebugRequest request) throws IOException {
    request.writeDelimitedTo(clientSocket.getOutputStream());
    clientSocket.getOutputStream().flush();
    return waitForResponse(request.getSequenceNumber());
  }

  private void eventReceived(DebugEvent event) {
    if (event.getSequenceNumber() == 0) {
      synchronized (unnumberedEvents) {
        unnumberedEvents.add(event);
        unnumberedEvents.notifyAll();
      }
      return;
    }
    synchronized (responses) {
      DebugEvent existing = responses.put(event.getSequenceNumber(), event);
      if (existing != null) {
        throw new AssertionError(
            "There's already an event in the response queue corresponding to sequence number "
                + event.getSequenceNumber());
      }
      responses.notifyAll();
    }
  }

  /**
   * Wait for a response from the debug server. Returns null if no response was received, or this
   * thread was interrupted.
   */
  @Nullable
  private DebugEvent waitForResponse(long sequence) {
    DebugEvent response = null;
    long startTime = System.currentTimeMillis();
    synchronized (responses) {
      while (response == null && shouldWaitForResponse(startTime)) {
        try {
          responses.wait(1000);
        } catch (InterruptedException e) {
          throw new AssertionError(e);
        }
        response = responses.remove(sequence);
      }
    }
    return response;
  }

  private boolean shouldWaitForResponse(long startTime) {
    return clientSocket.isConnected()
        && !readTask.isDone()
        && System.currentTimeMillis() - startTime < RESPONSE_TIMEOUT_MILLIS;
  }
}
