/*
 * Copyright 2014-2016 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.async;

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

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;

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

	private int progressPercent;
	private String message;

	private AsyncTaskListener listener;

	public AsyncTask (String threadName) {
		this.threadName = threadName;
		runnable = () -> {
			try {
				execute();
			} catch (Exception e) {
				Log.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. Note that this
	 * will also block main render thread.
	 */
	protected void executeOnOpenGL (final Runnable runnable) {
		final CountDownLatch latch = new CountDownLatch(1);

		AtomicReference<Exception> exceptionAt = new AtomicReference<>();

		Gdx.app.postRunnable(() -> {
			try {
				runnable.run();
			} catch (Exception e) {
				Log.exception(e);
				exceptionAt.set(e);
			}
			latch.countDown();
		});

		try {
			latch.await();

			Exception e = exceptionAt.get();
			if (e != null) {
				failed(e.getMessage(), e);
			}
		} 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) {
		Log.debug("AsyncTask::" + threadName, message);
		this.message = message;
		if (listener != null) listener.messageChanged(message);
	}

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

@@ -1089,36 +1089,8 @@
 ame;
-%0A%09private Runnable runnable;
 %0A%0A%09p
@@ -1255,16 +1255,25 @@
 Name;%0A%09%09
+Runnable 
 runnable
@@ -1326,32 +1326,66 @@
 (Exception e) %7B%0A
+%09%09%09%09Gdx.app.postRunnable(() -%3E %7B%0A%09
 %09%09%09%09Log.exceptio
@@ -1386,24 +1386,25 @@
 ception(e);%0A
+%09
 %09%09%09%09failed(e
@@ -1425,19 +1425,60 @@
  e);%0A%09%09%09
-%7D%0A%0A
+%09%7D);%0A%09%09%09%7D%0A%0A%09%09%09Gdx.app.postRunnable(() -%3E %7B%0A%09
 %09%09%09if (l
@@ -1515,16 +1515,23 @@
 shed();%0A
+%09%09%09%7D);%0A
 %09%09%7D;%0A%09%09t
@@ -1616,37 +1616,40 @@
 .start();%0A%09%7D%0A%0A%09p
-ublic
+rotected
  void failed (St
@@ -1714,29 +1714,32 @@
 son);%0A%09%7D%0A%0A%09p
-ublic
+rotected
  void failed
@@ -1830,21 +1830,24 @@
 ;%0A%09%7D%0A%0A%09p
-ublic
+rotected
  abstrac
@@ -2473,24 +2473,58 @@
  != null) %7B%0A
+%09%09%09%09Gdx.app.postRunnable(() -%3E %7B%0A%09
 %09%09%09%09failed(e
@@ -2538,24 +2538,32 @@
 sage(), e);%0A
+%09%09%09%09%7D);%0A
 %09%09%09%7D%0A%09%09%7D cat
@@ -2860,87 +2860,8 @@
 %09%7D%0A%0A
-%09public void setRunnable (Runnable runnable) %7B%0A%09%09this.runnable = runnable;%0A%09%7D%0A%0A
 %09pub
@@ -3028,16 +3028,48 @@
 essage;%0A
+%09%09Gdx.app.postRunnable(() -%3E %7B%0A%09
 %09%09if (li
@@ -3114,24 +3114,30 @@
 d(message);%0A
+%09%09%7D);%0A
 %09%7D%0A%0A%09public 

Fix AsyncTask, call listener from gdx thread