/*
 * Copyright 2014-2015 See AUTHORS file.
 *
 * 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.kotcrab.vis.editor.util;

import com.badlogic.gdx.Gdx;
import com.kotcrab.vis.editor.Log;
import com.kotcrab.vis.editor.ui.dialog.AsyncTaskProgressDialog;

import java.util.concurrent.CountDownLatch;

/**
 * Task that can be executed on another thread.
 * @author Kotcrab
 * @see AsyncTaskProgressDialog
 * @see AsyncTaskListener
 */
public abstract class AsyncTask {
	private Thread thread;
	private Runnable runnable;

	private int progressPercent;
	private String message;

	private AsyncTaskListener listener;

	public AsyncTask (String threadName) {
		runnable = () -> {
			try {
				execute();
			} catch (Exception e) {
				failed(e.getMessage(), e);
			}

			if (listener != null) listener.finished();
		};
		thread = new Thread(runnable, threadName);
	}

	public void start () {
		thread.start();
	}

	public void failed (String reason) {
		if (listener != null) listener.failed(reason);
	}

	public void failed (String reason, Exception ex) {
		if (listener != null) listener.failed(reason, ex);
	}

	public abstract void execute () throws Exception;

	/** Executes runnable on OpenGL thread. This methods blocks until runnable finished executing */
	protected void executeOnOpenGL (final Runnable runnable) {
		final CountDownLatch latch = new CountDownLatch(1);

		Gdx.app.postRunnable(() -> {
			runnable.run();
			latch.countDown();
		});

		try {
			latch.await();
		} catch (InterruptedException e) {
			Log.exception(e);
		}
	}

	public int getProgressPercent () {
		return progressPercent;
	}

	public void setProgressPercent (int progressPercent) {
		this.progressPercent = progressPercent;
		if (listener != null) listener.progressChanged(progressPercent);
	}

	public void setRunnable (Runnable runnable) {
		this.runnable = runnable;
	}

	public String getMessage () {
		return message;
	}

	public void setMessage (String message) {
		this.message = message;
		if (listener != null) listener.messageChanged(message);
	}

	public void setListener (AsyncTaskListener listener) {
		this.listener = listener;
	}
}

@@ -807,16 +807,68 @@
 wnLatch;
+%0Aimport java.util.concurrent.atomic.AtomicReference;
 %0A%0A/**%0A *
@@ -1287,16 +1287,38 @@
 on e) %7B%0A
+%09%09%09%09Log.exception(e);%0A
 %09%09%09%09fail
@@ -1748,16 +1748,20 @@
 n;%0A%0A%09/**
+%0A%09 *
  Execute
@@ -1842,16 +1842,74 @@
 xecuting
+. Note that this%0A%09 * will also block main render thread.%0A%09
  */%0A%09pro
@@ -2019,16 +2019,85 @@
 ch(1);%0A%0A
+%09%09AtomicReference%3CException%3E exceptionAt = new AtomicReference%3C%3E();%0A%0A
 %09%09Gdx.ap
@@ -2119,16 +2119,26 @@
 () -%3E %7B%0A
+%09%09%09try %7B%0A%09
 %09%09%09runna
@@ -2155,59 +2155,230 @@
 %0A%09%09%09
-latch.countDown();%0A%09%09%7D);%0A%0A%09%09try %7B%0A%09%09%09latch.await();
+%7D catch (Exception e) %7B%0A%09%09%09%09Log.exception(e);%0A%09%09%09%09exceptionAt.set(e);%0A%09%09%09%7D%0A%09%09%09latch.countDown();%0A%09%09%7D);%0A%0A%09%09try %7B%0A%09%09%09latch.await();%0A%0A%09%09%09Exception e = exceptionAt.get();%0A%09%09%09if (e != null) %7B%0A%09%09%09%09failed(e.getMessage(), e);%0A%09%09%09%7D
 %0A%09%09%7D

Fix AsyncTask not handling OpenGL exception properly