/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.remoteServer.util;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Progressive;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.concurrent.atomic.AtomicReference;

public abstract class CloudRuntimeTask<
  T,
  DC extends DeploymentConfiguration,
  SR extends CloudServerRuntimeInstance<DC, ?, ?>> {

  private static final Logger LOG = Logger.getInstance("#" + CloudRuntimeTask.class.getName());

  private final Project myProject;
  private final String myTitle;

  private final AtomicReference<Boolean> mySuccess = new AtomicReference<Boolean>();
  private final AtomicReference<String> myErrorMessage = new AtomicReference<String>();

  public CloudRuntimeTask(Project project, String title) {
    myProject = project;
    myTitle = title;
  }

  public T performSync() {
    return perform(true, null);
  }

  public void performAsync() {
    performAsync(null);
  }

  public void performAsync(Disposable disposable) {
    perform(false, disposable);
  }

  private T perform(boolean modal, final Disposable disposable) {
    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    final AtomicReference<T> result = new AtomicReference<T>();

    final Progressive progressive = new Progressive() {

      @Override
      public void run(@NotNull ProgressIndicator indicator) {
        indicator.setIndeterminate(true);
        while (!indicator.isCanceled()) {
          if (semaphore.waitFor(500)) {
            if (mySuccess.get()) {
              UIUtil.invokeLaterIfNeeded(new Runnable() {

                @Override
                public void run() {
                  if (disposable == null || !Disposer.isDisposed(disposable)) {
                    postPerform(result.get());
                  }
                }
              });
            }
            break;
          }
        }
      }
    };

    Task task;
    boolean cancellable = isCancellable(modal);
    if (modal) {
      task = new Task.Modal(myProject, myTitle, cancellable) {

        @Override
        public void run(@NotNull ProgressIndicator indicator) {
          progressive.run(indicator);
        }
      };
    }
    else {
      task = new Task.Backgroundable(myProject, myTitle, cancellable) {

        @Override
        public void run(@NotNull ProgressIndicator indicator) {
          progressive.run(indicator);
        }

        @Override
        public boolean shouldStartInBackground() {
          return CloudRuntimeTask.this.shouldStartInBackground();
        }
      };
    }

    mySuccess.set(false);
    myErrorMessage.set(null);

    run(semaphore, result);

    task.queue();

    return result.get();
  }

  protected boolean shouldStartInBackground() {
    return true;
  }

  protected void postPerform(T result) {

  }

  protected boolean isCancellable(boolean modal) {
    return modal;
  }

  protected void run(final Semaphore semaphore, final AtomicReference<T> result) {
    run(getServerRuntime(), semaphore, result);
  }

  protected void run(final SR serverRuntime, final Semaphore semaphore, final AtomicReference<T> result) {
    serverRuntime.getTaskExecutor().submit(new Runnable() {

      @Override
      public void run() {
        try {
          result.set(CloudRuntimeTask.this.run(serverRuntime));
          mySuccess.set(true);
        }
        catch (ServerRuntimeException e) {
          runtimeErrorOccurred(e.getMessage());
        }
        finally {
          semaphore.up();
        }
      }
    });
  }

  protected void runtimeErrorOccurred(@NotNull String errorMessage) {
    myErrorMessage.set(errorMessage);
    LOG.info(errorMessage);
  }

  public void showMessageDialog(JComponent component, String successMessage, String title) {
    if (mySuccess.get()) {
      Messages.showInfoMessage(component, successMessage, title);
      return;
    }
    String errorMessage = myErrorMessage.get();
    if (errorMessage != null) {
      Messages.showErrorDialog(component, errorMessage, title);
    }
  }

  protected abstract SR getServerRuntime();

  protected abstract T run(SR serverRuntime) throws ServerRuntimeException;
}
