package org.openlca.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.openlca.app.navigation.ModelTypeComparison;
import org.openlca.app.util.Labels;
import org.openlca.core.database.Daos;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.ParameterDao;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.descriptors.BaseDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Search implements Runnable {

	private Logger log = LoggerFactory.getLogger(getClass());
	private IDatabase database;

	ModelType typeFilter;
	private String rawTerm;
	private String[] terms;
	private List<BaseDescriptor> result = new ArrayList<>();

	public Search(IDatabase database, String term) {
		this.database = database;
		this.rawTerm = term == null ? "" : term.toLowerCase().trim();
		terms = rawTerm.split(" ");
		for (int i = 0; i < terms.length; i++)
			terms[i] = terms[i].trim();
	}

	public List<BaseDescriptor> getResult() {
		return result;
	}

	@Override
	public void run() {
		result.clear();
		if (rawTerm.isEmpty())
			return;
		log.trace("run search with term {}", rawTerm);
		ModelType[] types = typeFilter == null ? getSearchTypes()
				: new ModelType[] { typeFilter };
		for (ModelType type : types) {
			List<?> descriptors = getDescriptors(type);
			fetchResults(descriptors);
		}
		Collections.sort(result, new ResultComparator());
		log.trace("{} results fetched and ranked", result.size());
	}

	private ModelType[] getSearchTypes() {
		return ModelTypeComparison.getOrderedTypes();
	}

	private List<?> getDescriptors(ModelType type) {
		if (type == ModelType.PARAMETER)
			return new ParameterDao(database).getGlobalDescriptors();
		return Daos.createRootDao(database, type).getDescriptors();
	}

	private void fetchResults(List<?> descriptors) {
		for (Object obj : descriptors) {
			if (!(obj instanceof BaseDescriptor))
				continue;
			BaseDescriptor descriptor = (BaseDescriptor) obj;
			if (match(descriptor))
				result.add(descriptor);
		}
	}

	private boolean match(BaseDescriptor descriptor) {
		String label = Labels.getDisplayName(descriptor);
		if (terms == null || label == null)
			return false;
		String feed = label.toLowerCase();
		for (String term : terms) {
			if (!feed.contains(term))
				return false;
		}
		return true;
	}

	private class ResultComparator implements Comparator<BaseDescriptor> {
		@Override
		public int compare(BaseDescriptor o1, BaseDescriptor o2) {
			String label1 = Labels.getDisplayName(o1).toLowerCase();
			String label2 = Labels.getDisplayName(o2).toLowerCase();
			for (String term : terms) {
				int idx1 = label1.indexOf(term);
				int idx2 = label2.indexOf(term);
				int diff = idx1 - idx2;
				if (diff != 0)
					return diff;
			}
			return label1.compareToIgnoreCase(label2);
		}
	}
}

@@ -2143,20 +2143,171 @@
 or d
-escriptor) %7B
+) %7B%0A%09%09if (terms == null)%0A%09%09%09return false;%0A%09%09if (terms.length == 1%0A%09%09%09%09&& d.getRefId() != null%0A%09%09%09%09&& d.getRefId().equalsIgnoreCase(terms%5B0%5D)) %7B%0A%09%09%09return true;%0A%09%09%7D
 %0A%09%09S
@@ -2347,43 +2347,17 @@
 me(d
-escriptor);%0A%09%09if (terms == null %7C%7C 
+);%0A%09%09if (
 labe

support search by UUIDs