package bndtools;

import java.io.File;
import java.util.Hashtable;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.url.URLConstants;
import org.osgi.service.url.URLStreamHandlerService;

import aQute.bnd.build.ReflectAction;
import aQute.bnd.osgi.Processor;
import aQute.bnd.service.action.Action;

/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends AbstractUIPlugin {

	// The plug-in ID
	public static final String								PLUGIN_ID	= "aQute.bmaker";

	// The shared instance
	public static volatile Activator						instance;
	BundleContext											context;
	private ServiceRegistration<URLStreamHandlerService>	dataUrlHandlerReg;

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.
	 * BundleContext )
	 */
	@Override
	public void start(BundleContext context) throws Exception {
		super.start(context);
		instance = this;
		this.context = context;

		Hashtable<String, Object> p = new Hashtable<>();
		// p.put(Action.ACTION_MENU, new String[] {"a:b", "a:c", "a:d",
		// "a:d:e"});
		context.registerService(Action.class.getName(), new ReflectAction(""), p);

		Hashtable<String, Object> dataUrlHandlerProps = new Hashtable<>();
		dataUrlHandlerProps.put(URLConstants.URL_HANDLER_PROTOCOL, DataURLStreamHandler.PROTOCOL);
		dataUrlHandlerReg = context.registerService(URLStreamHandlerService.class, new DataURLStreamHandler(),
			dataUrlHandlerProps);
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.
	 * BundleContext )
	 */
	@Override
	public void stop(BundleContext context) throws Exception {
		dataUrlHandlerReg.unregister();
		instance = null;
		super.stop(context);
	}

	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static Activator getDefault() {
		return instance;
	}

	/**
	 * Returns an image descriptor for the image file at the given plug-in
	 * relative path
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}

	static volatile boolean busy;

	public void error(final String msg, final Throwable t) {
		Status s = new Status(IStatus.ERROR, PLUGIN_ID, 0, msg, t);
		getLog().log(s);
		async(new Runnable() {
			@Override
			public void run() {
				synchronized (this) {
					if (busy)
						return;
					busy = true;
				}
				Status s = new Status(IStatus.ERROR, PLUGIN_ID, 0, "", null);
				ErrorDialog.openError(null, "Errors during bundle generation", msg + " " + t.getMessage(), s);

				busy = false;
			}
		});
	}

	public void info(String msg) {
		Status s = new Status(IStatus.INFO, PLUGIN_ID, 0, msg, null);
		getLog().log(s);
	}

	public static void error(List<String> errors) {
		final StringBuffer sb = new StringBuffer();
		for (String msg : errors) {
			sb.append(msg);
			sb.append("\n");
		}

		async(() -> {
			Status s = new Status(IStatus.ERROR, PLUGIN_ID, 0, "", null);
			ErrorDialog.openError(null, "Errors during bundle generation", sb.toString(), s);
		});
	}

	public static void message(final String msg) {
		async(() -> MessageDialog.openInformation(null, "Bnd", msg));
	}

	public static void warning(List<String> errors) {
		final StringBuffer sb = new StringBuffer();
		for (String msg : errors) {
			sb.append(msg);
			sb.append("\n");
		}
		async(() -> {
			Status s = new Status(IStatus.WARNING, PLUGIN_ID, 0, "", null);
			ErrorDialog.openError(null, "Warnings during bundle generation", sb.toString(), s);
		});
	}

	static void async(Runnable run) {
		if (Display.getCurrent() == null) {
			Display.getDefault()
				.asyncExec(run);
		} else
			run.run();
	}

	public static boolean getReportDone() {
		return true;
		// return
		// getPreferenceStore().getBoolean(PreferenceConstants.P_REPORT_DONE);
	}

	public static File getCopy() {
		return null;

		// String path =
		// getPreferenceStore().getString(PreferenceConstants.P_COPY);
		// if ( path == null )
		// return null;

		// File file = new File(path);
		// if ( !file.exists() || file.isFile() )
		// return null;

		// return file;
	}

	public static boolean isPedantic() {
		return false;
		// IPreferenceStore store = getPreferenceStore();
		// return store.getBoolean(PreferenceConstants.P_PEDANTIC);
	}

	public BundleContext getBundleContext() {
		return context;
	}

	public static void report(boolean warnings, @SuppressWarnings("unused") boolean acknowledge, Processor reporter,
		final String title, final String extra) {
		if (reporter.getErrors()
			.size() > 0
			|| (warnings && reporter.getWarnings()
				.size() > 0)) {
			final StringBuffer sb = new StringBuffer();
			sb.append("\n");
			if (reporter.getErrors()
				.size() > 0) {
				sb.append("[Errors]\n");
				for (String msg : reporter.getErrors()) {
					sb.append(msg);
					sb.append("\n");
				}
			}
			sb.append("\n");
			if (reporter.getWarnings()
				.size() > 0) {
				sb.append("[Warnings]\n");
				for (String msg : reporter.getWarnings()) {
					sb.append(msg);
					sb.append("\n");
				}
			}
			final Status s = new Status(IStatus.ERROR, PLUGIN_ID, 0, sb.toString(), null);
			reporter.clear();

			async(() -> ErrorDialog.openError(null, title, title + "\n" + extra, s));

		} else {
			message(title + " : ok");
		}
	}

}
