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

import com.intellij.concurrency.JobScheduler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationActivationListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.util.concurrency.QueueProcessor;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

public class Alarm implements Disposable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.util.Alarm");

  private volatile boolean myDisposed;

  private final List<Request> myRequests = new SmartList<Request>();
  private final List<Request> myPendingRequests = new SmartList<Request>();

  private final ExecutorService myExecutorService;

  private static final ThreadPoolExecutor ourSharedExecutorService = ConcurrencyUtil.newSingleThreadExecutor("Alarm pool(shared)", Thread.NORM_PRIORITY - 2);

  private final Object LOCK = new Object();
  protected final ThreadToUse myThreadToUse;

  private JComponent myActivationComponent;

  @Override
  public void dispose() {
    myDisposed = true;
    cancelAllRequests();

    if (myThreadToUse == ThreadToUse.POOLED_THREAD) {
      myExecutorService.shutdown();
    }
    else if (myThreadToUse == ThreadToUse.OWN_THREAD) {
      myExecutorService.shutdown();
      ((ThreadPoolExecutor)myExecutorService).getQueue().clear();
    }
  }

  public void checkDisposed() {
    LOG.assertTrue(!myDisposed, "Already disposed");
  }

  public enum ThreadToUse {
    SWING_THREAD,
    SHARED_THREAD,
    POOLED_THREAD,
    OWN_THREAD
  }

  /**
   * Creates alarm that works in Swing thread
   */
  public Alarm() {
    this(ThreadToUse.SWING_THREAD);
  }

  public Alarm(Disposable parentDisposable) {
    this(ThreadToUse.SWING_THREAD, parentDisposable);
  }

  public Alarm(@NotNull ThreadToUse threadToUse) {
    this(threadToUse, null);
    LOG.assertTrue(threadToUse != ThreadToUse.POOLED_THREAD && threadToUse != ThreadToUse.OWN_THREAD,
                   "You must provide parent Disposable for ThreadToUse.POOLED_THREAD and ThreadToUse.OWN_THREAD Alarm");
  }

  public Alarm(@NotNull ThreadToUse threadToUse, @Nullable Disposable parentDisposable) {
    myThreadToUse = threadToUse;

    if (threadToUse == ThreadToUse.POOLED_THREAD) {
      myExecutorService = new MyExecutor();
    }
    else if(threadToUse == ThreadToUse.OWN_THREAD) {
      myExecutorService = ConcurrencyUtil.newSingleThreadExecutor(
        "Alarm pool(own)", Thread.NORM_PRIORITY - 2);
    }
    else {
      myExecutorService = ourSharedExecutorService;
    }

    if (parentDisposable != null) {
      Disposer.register(parentDisposable, this);
    }
  }

  public void addRequest(@NotNull final Runnable request, final int delay, boolean runWithActiveFrameOnly) {
    if (runWithActiveFrameOnly && !ApplicationManager.getApplication().isActive()) {
      final MessageBus bus = ApplicationManager.getApplication().getMessageBus();
      final MessageBusConnection connection = bus.connect(this);
      connection.subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener.Adapter() {
        @Override
        public void applicationActivated(IdeFrame ideFrame) {
          connection.disconnect();
          addRequest(request, delay);
        }
      });
    } else {
      addRequest(request, delay);
    }
  }

  public void addRequest(@NotNull Runnable request, long delayMillis) {
    _addRequest(request, delayMillis, myThreadToUse == ThreadToUse.SWING_THREAD ? ModalityState.current() : null);
  }

  public void addRequest(@NotNull Runnable request, int delayMillis) {
    _addRequest(request, delayMillis, myThreadToUse == ThreadToUse.SWING_THREAD ? ModalityState.current() : null);
  }

  public void addComponentRequest(@NotNull Runnable request, int delay) {
    assert myActivationComponent != null;
    _addRequest(request, delay, ModalityState.stateForComponent(myActivationComponent));
  }

  public void addComponentRequest(@NotNull Runnable request, long delayMillis) {
    assert myActivationComponent != null;
    _addRequest(request, delayMillis, ModalityState.stateForComponent(myActivationComponent));
  }

  public void addRequest(@NotNull Runnable request, int delayMillis, @Nullable final ModalityState modalityState) {
    LOG.assertTrue(myThreadToUse == ThreadToUse.SWING_THREAD);
    _addRequest(request, delayMillis, modalityState);
  }

  public void addRequest(@NotNull Runnable request, long delayMillis, @Nullable final ModalityState modalityState) {
    LOG.assertTrue(myThreadToUse == ThreadToUse.SWING_THREAD);
    _addRequest(request, delayMillis, modalityState);
  }

  protected void _addRequest(@NotNull Runnable request, long delayMillis, ModalityState modalityState) {
    synchronized (LOCK) {
      checkDisposed();
      final Request requestToSchedule = new Request(request, modalityState, delayMillis);

      if (myActivationComponent == null || myActivationComponent.isShowing()) {
        _add(requestToSchedule);
      }
      else {
        if (!myPendingRequests.contains(requestToSchedule)) {
          myPendingRequests.add(requestToSchedule);
        }
      }
    }
  }

  private void _add(@NotNull Request requestToSchedule) {
    final ScheduledFuture<?> future = JobScheduler.getScheduler().schedule(requestToSchedule, requestToSchedule.myDelay, TimeUnit.MILLISECONDS);
    requestToSchedule.setFuture(future);
    myRequests.add(requestToSchedule);
  }

  private void flushPending() {
    for (Request each : myPendingRequests) {
      _add(each);
    }

    myPendingRequests.clear();
  }

  public boolean cancelRequest(@NotNull Runnable request) {
    synchronized (LOCK) {
      cancelRequest(request, myRequests);
      cancelRequest(request, myPendingRequests);
      return true;
    }
  }

  private void cancelRequest(@NotNull Runnable request, @NotNull List<Request> list) {
    for (int i = list.size()-1; i>=0; i--) {
      Request r = list.get(i);
      if (r.getTask() == request) {
        r.cancel();
        list.remove(i);
      }
    }
  }

  public int cancelAllRequests() {
    synchronized (LOCK) {
      int count = cancelAllRequests(myRequests);
      cancelAllRequests(myPendingRequests);
      return count;
    }
  }

  private int cancelAllRequests(@NotNull List<Request> list) {
    int count = 0;
    for (Request request : list) {
      count++;
      request.cancel();
    }
    list.clear();
    return count;
  }

  public void flush() {
    List<Pair<Request, Runnable>> requests;
    synchronized (LOCK) {
      if (myRequests.isEmpty()) {
        return;
      }

      requests = new SmartList<Pair<Request, Runnable>>();
      for (Request request : myRequests) {
        Runnable existingTask = request.cancel();
        if (existingTask != null) {
          requests.add(Pair.create(request, existingTask));
        }
      }
      myRequests.clear();
    }

    for (Pair<Request, Runnable> request : requests) {
      synchronized (LOCK) {
        request.first.myTask = request.second;
      }
      request.first.run();
    }
  }

  public int getActiveRequestCount() {
    synchronized (LOCK) {
      return myRequests.size();
    }
  }

  public boolean isEmpty() {
    synchronized (LOCK) {
      return myRequests.isEmpty();
    }
  }

  protected boolean isEdt() {
    return isEventDispatchThread();
  }

  public static boolean isEventDispatchThread() {
    final Application app = ApplicationManager.getApplication();
    return app != null && app.isDispatchThread() || EventQueue.isDispatchThread();
  }

  private class Request implements Runnable {
    private Runnable myTask; // guarded by LOCK
    private final ModalityState myModalityState;
    private Future<?> myFuture; // guarded by LOCK
    private final long myDelay;

    private Request(@NotNull final Runnable task, @Nullable ModalityState modalityState, long delayMillis) {
      synchronized (LOCK) {
        myTask = task;
        myModalityState = modalityState;
        myDelay = delayMillis;
      }
    }

    @Override
    public void run() {
      try {
        if (myDisposed) {
          return;
        }
        synchronized (LOCK) {
          if (myTask == null) {
            return;
          }
        }

        final Runnable scheduledTask = new Runnable() {
          @Override
          public void run() {
            final Runnable task;
            synchronized (LOCK) {
              task = myTask;
              if (task == null) return;
              myTask = null;

              myRequests.remove(Request.this);
              myFuture = null;
            }

            if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
              //noinspection SSBasedInspection
              SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                  if (!myDisposed) {
                    QueueProcessor.runSafely(task);
                  }
                }
              });
            }
            else {
              QueueProcessor.runSafely(task);
            }
          }

          @Override
          public String toString() {
            return "ScheduledTask "+Request.this;
          }
        };

        if (myModalityState == null) {
          Future<?> future = myExecutorService.submit(scheduledTask);
          synchronized (LOCK) {
            myFuture = future;
          }
        }
        else {
          final Application app = ApplicationManager.getApplication();
          if (app == null) {
            //noinspection SSBasedInspection
            SwingUtilities.invokeLater(scheduledTask);
          }
          else if (app.isDispatchThread() && app.getCurrentModalityState().equals(myModalityState)) {
            scheduledTask.run();
          }
          else {
            app.invokeLater(scheduledTask, myModalityState);
          }
        }
      }
      catch (Throwable e) {
        LOG.error(e);
      }
    }

    private Runnable getTask() {
      synchronized (LOCK) {
        return myTask;
      }
    }

    public void setFuture(@NotNull ScheduledFuture<?> future) {
      synchronized (LOCK) {
        myFuture = future;
      }
    }

    public ModalityState getModalityState() {
      return myModalityState;
    }

    /**
     * @return task if not yet executed
     */
    @Nullable
    private Runnable cancel() {
      synchronized (LOCK) {
        if (myFuture != null) {
          myFuture.cancel(false);
          // TODO Use java.util.concurrent.ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true) when on jdk 1.7
          ((ScheduledThreadPoolExecutor)JobScheduler.getScheduler()).remove((Runnable)myFuture);
          myFuture = null;
        }
        Runnable task = myTask;
        myTask = null;
        return task;
      }
    }

    @Override
    public String toString() {
      Runnable task = getTask();
      return super.toString() + (task != null ? ": "+task : "");
    }
  }

  public Alarm setActivationComponent(@NotNull final JComponent component) {
    myActivationComponent = component;
    new UiNotifyConnector(component, new Activatable() {
      @Override
      public void showNotify() {
        flushPending();
      }

      @Override
      public void hideNotify() {
      }
    });


    return this;
  }

  public boolean isDisposed() {
    return myDisposed;
  }

  private class MyExecutor extends AbstractExecutorService {
    private final AtomicBoolean isShuttingDown = new AtomicBoolean();
    private final QueueProcessor<Runnable> myProcessor = QueueProcessor.createRunnableQueueProcessor();

    @Override
    public void shutdown() {
      myProcessor.clear();
      isShuttingDown.set(myDisposed);
    }

    @NotNull
    @Override
    public List<Runnable> shutdownNow() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isShutdown() {
      return isShuttingDown.get();
    }

    @Override
    public boolean isTerminated() {
      return isShutdown() && myProcessor.isEmpty();
    }

    @Override
    public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
      throw new UnsupportedOperationException();
    }

    @Override
    public void execute(@NotNull Runnable command) {
      myProcessor.add(command);
    }
  }
}
