package org.cytoscape.app.internal.task;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.cytoscape.app.internal.manager.App;
import org.cytoscape.app.internal.manager.App.AppStatus;
import org.cytoscape.app.internal.manager.AppManager;
import org.cytoscape.app.internal.net.WebApp;
import org.cytoscape.app.internal.net.WebQuerier;
import org.cytoscape.work.AbstractTask;
import org.cytoscape.work.ObservableTask;
import org.cytoscape.work.TaskMonitor;
import org.cytoscape.work.json.JSONResult;
import org.json.JSONException;
import org.json.JSONObject;

public class ListAppsTask extends AbstractAppTask implements ObservableTask {
	AppStatus status;
	public ListAppsTask(final AppManager appManager, final AppStatus status) {
		super(appManager);
		this.status = status;
	}

	@Override
	public void run(TaskMonitor taskMonitor) throws Exception {
		taskMonitor.setTitle("Listing "+status.toString()+" apps");
		updateApps();
	}

	@Override
	public List<Class<?>> getResultClasses() {
		return Arrays.asList(List.class, String.class, JSONResult.class);
	}
	
	public void appendJSONField(JSONObject appJSON, final String field, final String value) {
		
		try {
			appJSON.put(field, value);
		} catch (JSONException e) {
			try {
				appJSON.put(field, "#Invalid JSON#");
			} catch (JSONException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		
	}
	
	@SuppressWarnings({ "unchecked" })
	@Override
	public <R> R getResults(Class<? extends R> type) {
		List<App> statusAppList = getApps(status);
		if (type.equals(JSONResult.class)) {
			JSONResult res = () -> {
				StringBuilder stringBuilder = new StringBuilder("[");
				int count = statusAppList.size();
				int index = 0;
				for (App app: statusAppList) {
					JSONObject appJSON = new JSONObject();
					appendJSONField(appJSON, "appName", app.getAppName());
					appendJSONField(appJSON, "version", app.getVersion());
					appendJSONField(appJSON, "description", app.getDescription());
					appendJSONField(appJSON, "status", app.getReadableStatus());
					stringBuilder.append(appJSON.toString());
					index++;
					if (index < count)
						stringBuilder.append(",");
				}
				stringBuilder.append("]");
				return stringBuilder.toString();
			};
			return (R)res;
		} else if (type.equals(String.class)) {
			List<String> appList = new ArrayList<String>(statusAppList.size());
			for (App app: statusAppList) {
				appList.add("name: "+app.getAppName()+
				            ", version: "+app.getVersion()+
				            ", status: "+app.getReadableStatus());
			}
			Collections.sort(appList);
			String list = "";
			for (String app: appList) {
				list += app+"\n";
			}
			return (R)list;
		} else if (type.equals(List.class)) {
			List<String> list = new ArrayList<>();
			for (App app: statusAppList) {
				list.add(app.getAppName());
			}
			return (R)list;
		}
		return null;
	}

}

@@ -1208,69 +1208,32 @@
 lic 
-void appendJSONField(JSONObject appJSON, final String field, 
+static String jsonQuote(
 fina
@@ -1245,233 +1245,106 @@
 ing 
-value
+input
 ) %7B%0A%09%09
-%0A%09%09try %7B%0A%09%09%09appJSON.put(field, value);%0A%09%09%7D catch (JSONException e) %7B%0A%09%09%09try %7B%0A%09%09%09%09appJSON.put(field, %22#Invalid JSON#%22)
+if (input == null) %7B%0A%09%09%09return null
 ;%0A
-%09
 %09%09%7D 
-catch (JSONException e1) %7B%0A%09%09%09%09e1.printStackTrace();%0A%09%09%09%7D%0A%09%09%09e.printStackTrace(
+else %7B%0A%09%09%09return JSONObject.quote(input
 );%0A%09%09%7D%0A
-%09%09%0A
 %09%7D%0A%09
@@ -1714,88 +1714,62 @@
 %09%09%09%09
-JSONObject appJSON = new JSONObject();%0A%09%09%09%09%09appendJSONField(appJSON, %22appName%22, 
+%0A%09%09%09%09%09stringBuilder.append(%22%7B%5C%22appName%5C%22: %22+jsonQuote(
 app.
@@ -1785,51 +1785,67 @@
 e())
++%22,%22)
 ;%0A%09%09%09%09%09
-appendJSONField(appJSON, %22version%22, 
+stringBuilder.append(%22%5C%22version%5C%22: %22+jsonQuote(
 app.
@@ -1861,55 +1861,71 @@
 n())
++%22,%22)
 ;%0A%09%09%09%09%09
-appendJSONField(appJSON, %22description%22, 
+stringBuilder.append(%22%5C%22description%5C%22: %22+jsonQuote(
 app.
@@ -1945,120 +1945,94 @@
 n())
++%22,%22)
 ;%0A%09%09%09%09%09
-appendJSONField(appJSON, %22status%22, app.getReadableStatus());%0A%09%09%09%09%09stringBuilder.append(appJSON.toString()
+stringBuilder.append(%22%5C%22status%5C%22: %22+jsonQuote(app.getReadableStatus())+%22%7D%22
 );%0A%09

Add escape characters to App JSON fields while respecting NULL values