/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.beam.runners.fnexecution.jobsubmission;

import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Throwables.getRootCause;
import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Throwables.getStackTraceAsString;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.beam.model.jobmanagement.v1.JobApi;
import org.apache.beam.model.jobmanagement.v1.JobApi.JobMessage;
import org.apache.beam.model.jobmanagement.v1.JobApi.JobState;
import org.apache.beam.model.jobmanagement.v1.JobApi.JobState.Enum;
import org.apache.beam.model.jobmanagement.v1.JobApi.JobStateEvent;
import org.apache.beam.model.pipeline.v1.RunnerApi;
import org.apache.beam.model.pipeline.v1.RunnerApi.Pipeline;
import org.apache.beam.runners.fnexecution.provisioning.JobInfo;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.vendor.grpc.v1p26p0.com.google.protobuf.util.Timestamps;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.util.concurrent.FutureCallback;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.util.concurrent.Futures;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.util.concurrent.ListenableFuture;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.util.concurrent.ListeningExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Internal representation of a Job which has been invoked (prepared and run) by a client. */
public class JobInvocation {

  private static final Logger LOG = LoggerFactory.getLogger(JobInvocation.class);

  private final RunnerApi.Pipeline pipeline;
  private final PortablePipelineRunner pipelineRunner;
  private final JobInfo jobInfo;
  private final ListeningExecutorService executorService;
  private final List<JobStateEvent> stateHistory;
  private final List<JobMessage> messageHistory;
  private final List<Consumer<JobStateEvent>> stateObservers;
  private final List<Consumer<JobMessage>> messageObservers;
  private JobApi.MetricResults metrics;
  private PortablePipelineResult resultHandle;
  @Nullable private ListenableFuture<PortablePipelineResult> invocationFuture;

  public JobInvocation(
      JobInfo jobInfo,
      ListeningExecutorService executorService,
      Pipeline pipeline,
      PortablePipelineRunner pipelineRunner) {
    this.jobInfo = jobInfo;
    this.executorService = executorService;
    this.pipeline = pipeline;
    this.pipelineRunner = pipelineRunner;
    this.stateObservers = new ArrayList<>();
    this.messageObservers = new ArrayList<>();
    this.invocationFuture = null;
    this.stateHistory = new ArrayList<>();
    this.messageHistory = new ArrayList<>();
    this.metrics = JobApi.MetricResults.newBuilder().build();
    this.setState(JobState.Enum.STOPPED);
  }

  private PortablePipelineResult runPipeline() throws Exception {
    return pipelineRunner.run(pipeline, jobInfo);
  }

  /** Start the job. */
  public synchronized void start() {
    LOG.info("Starting job invocation {}", getId());
    if (getState() != JobState.Enum.STOPPED) {
      throw new IllegalStateException(String.format("Job %s already running.", getId()));
    }
    setState(JobState.Enum.STARTING);
    invocationFuture = executorService.submit(this::runPipeline);
    // TODO: Defer transitioning until the pipeline is up and running.
    setState(JobState.Enum.RUNNING);
    Futures.addCallback(
        invocationFuture,
        new FutureCallback<PortablePipelineResult>() {
          @Override
          public void onSuccess(PortablePipelineResult pipelineResult) {
            if (pipelineResult != null) {
              PipelineResult.State state = pipelineResult.getState();

              if (state.isTerminal()) {
                metrics = pipelineResult.portableMetrics();
              } else {
                resultHandle = pipelineResult;
              }

              switch (state) {
                case DONE:
                  setState(Enum.DONE);
                  break;
                case RUNNING:
                  setState(Enum.RUNNING);
                  break;
                case CANCELLED:
                  setState(Enum.CANCELLED);
                  break;
                case FAILED:
                  setState(Enum.FAILED);
                  break;
                default:
                  setState(JobState.Enum.UNSPECIFIED);
              }
            } else {
              setState(JobState.Enum.UNSPECIFIED);
            }
          }

          @Override
          public void onFailure(@Nonnull Throwable throwable) {
            if (throwable instanceof CancellationException) {
              // We have canceled execution, just update the job state
              setState(JobState.Enum.CANCELLED);
              return;
            }
            String message = String.format("Error during job invocation %s.", getId());
            LOG.error(message, throwable);
            sendMessage(
                JobMessage.newBuilder()
                    .setMessageText(getStackTraceAsString(throwable))
                    .setImportance(JobMessage.MessageImportance.JOB_MESSAGE_DEBUG)
                    .build());
            sendMessage(
                JobMessage.newBuilder()
                    .setMessageText(getRootCause(throwable).toString())
                    .setImportance(JobMessage.MessageImportance.JOB_MESSAGE_ERROR)
                    .build());
            setState(JobState.Enum.FAILED);
          }
        },
        executorService);
  }

  /** @return Unique identifier for the job invocation. */
  public String getId() {
    return jobInfo.jobId();
  }

  /** Cancel the job. */
  public synchronized void cancel() {
    LOG.info("Canceling job invocation {}", getId());
    if (this.invocationFuture != null) {
      this.invocationFuture.cancel(true /* mayInterruptIfRunning */);
      Futures.addCallback(
          invocationFuture,
          new FutureCallback<PortablePipelineResult>() {
            @Override
            public void onSuccess(PortablePipelineResult pipelineResult) {
              // Do not cancel when we are already done.
              if (pipelineResult != null
                  && pipelineResult.getState() != PipelineResult.State.DONE) {
                try {
                  pipelineResult.cancel();
                  setState(JobState.Enum.CANCELLED);
                } catch (IOException exn) {
                  throw new RuntimeException(exn);
                }
              }
            }

            @Override
            public void onFailure(Throwable throwable) {}
          },
          executorService);
    }
  }

  public JobApi.MetricResults getMetrics() {
    if (resultHandle != null) {
      metrics = resultHandle.portableMetrics();
    }
    return metrics;
  }

  /** Retrieve the job's current state. */
  public JobState.Enum getState() {
    return getStateEvent().getState();
  }

  /** Retrieve the job's current state. */
  public JobStateEvent getStateEvent() {
    return stateHistory.get(stateHistory.size() - 1);
  }

  /** Retrieve the job's pipeline. */
  public RunnerApi.Pipeline getPipeline() {
    return this.pipeline;
  }

  /** Listen for job state changes with a {@link Consumer}. */
  public synchronized void addStateListener(Consumer<JobStateEvent> stateStreamObserver) {
    for (JobStateEvent event : stateHistory) {
      stateStreamObserver.accept(event);
    }
    stateObservers.add(stateStreamObserver);
  }

  /** Listen for job messages with a {@link Consumer}. */
  public synchronized void addMessageListener(Consumer<JobMessage> messageStreamObserver) {
    for (JobMessage msg : messageHistory) {
      messageStreamObserver.accept(msg);
    }
    messageObservers.add(messageStreamObserver);
  }

  /** Convert to {@link JobApi.JobInfo}. */
  public JobApi.JobInfo toProto() {
    return JobApi.JobInfo.newBuilder()
        .setJobId(jobInfo.jobId())
        .setJobName(jobInfo.jobName())
        .setPipelineOptions(jobInfo.pipelineOptions())
        .setState(getState())
        .build();
  }

  private synchronized void setState(JobState.Enum state) {
    JobStateEvent event =
        JobStateEvent.newBuilder()
            .setState(state)
            .setTimestamp(Timestamps.fromMillis(System.currentTimeMillis()))
            .build();
    this.stateHistory.add(event);
    for (Consumer<JobStateEvent> observer : stateObservers) {
      observer.accept(event);
    }
  }

  private synchronized void sendMessage(JobMessage message) {
    messageHistory.add(message);
    for (Consumer<JobMessage> observer : messageObservers) {
      observer.accept(message);
    }
  }

  static Boolean isTerminated(Enum state) {
    switch (state) {
      case DONE:
      case FAILED:
      case CANCELLED:
      case DRAINED:
        return true;
      default:
        return false;
    }
  }
}
