/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.test.internal.performance.results.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.test.internal.performance.eval.StatisticsUtil;
import org.eclipse.test.internal.performance.results.db.AbstractResults;
import org.eclipse.test.internal.performance.results.db.BuildResults;
import org.eclipse.test.internal.performance.results.db.ConfigResults;
import org.eclipse.test.internal.performance.results.db.DB_Results;
import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
import org.eclipse.test.internal.performance.results.utils.Util;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertyDescriptor;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import org.osgi.service.prefs.BackingStoreException;

/**
 * An Organization Element
 */
public abstract class ResultsElement implements IAdaptable, IPropertySource, IWorkbenchAdapter, Comparable<ResultsElement> {

	// Image descriptors
	private static final ISharedImages WORKBENCH_SHARED_IMAGES = PlatformUI.getWorkbench().getSharedImages();
	public static final Image ERROR_IMAGE = WORKBENCH_SHARED_IMAGES.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
	public static final ImageDescriptor ERROR_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_OBJS_ERROR_TSK);
	public static final Image WARN_IMAGE = WORKBENCH_SHARED_IMAGES.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
	public static final ImageDescriptor WARN_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_OBJS_WARN_TSK);
	public static final Image INFO_IMAGE = WORKBENCH_SHARED_IMAGES.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
	public static final ImageDescriptor INFO_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK);
	public static final Image HELP_IMAGE = WORKBENCH_SHARED_IMAGES.getImage(ISharedImages.IMG_LCL_LINKTO_HELP);
	public static final ImageDescriptor HELP_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_LCL_LINKTO_HELP);
	public static final ImageDescriptor FOLDER_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_OBJ_FOLDER);
	public static final ImageDescriptor CONNECT_IMAGE_DESCRIPTOR = WORKBENCH_SHARED_IMAGES.getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED);

	// Model
    ResultsElement parent;
	AbstractResults results;
	ResultsElement[] children;
	String name;
	int status = -1;

	// Stats
    double[] statistics;

	// Status constants
	// state
	static final int UNKNOWN = 0x01;
	static final int UNREAD = 0x02;
	static final int READ = 0x04;
	static final int MISSING = 0x08;
	public static final int STATE_MASK = 0x0F;
	// info
	static final int SMALL_VALUE = 0x0010;
	static final int STUDENT_TTEST = 0x0020;
	public static final int INFO_MASK = 0x0030;
	// warning
	static final int NO_BASELINE = 0x0040;
	static final int SINGLE_RUN = 0x0080;
	static final int BIG_ERROR = 0x0100;
	static final int NOT_STABLE = 0x0200;
	static final int NOT_RELIABLE = 0x0400;
	public static final int WARNING_MASK = 0x0FC0;
	// error
	static final int BIG_DELTA = 0x1000;
	public static final int ERROR_MASK = 0xF000;

	// Property descriptors
	static final String P_ID_STATUS_INFO = "ResultsElement.status_info"; //$NON-NLS-1$
	static final String P_ID_STATUS_WARNING = "ResultsElement.status_warning"; //$NON-NLS-1$
	static final String P_ID_STATUS_ERROR = "ResultsElement.status_error"; //$NON-NLS-1$
	static final String P_ID_STATUS_COMMENT = "ResultsElement.status_comment"; //$NON-NLS-1$

	static final String P_STR_STATUS_INFO = " info"; //$NON-NLS-1$
	static final String P_STR_STATUS_WARNING = "warning"; //$NON-NLS-1$
	static final String P_STR_STATUS_ERROR = "error"; //$NON-NLS-1$
	static final String P_STR_STATUS_COMMENT = "comment"; //$NON-NLS-1$
	static final String[] NO_VALUES = new String[0];

	private static Vector<IPropertyDescriptor> DESCRIPTORS;
	static final TextPropertyDescriptor COMMENT_DESCRIPTOR = new TextPropertyDescriptor(P_ID_STATUS_COMMENT, P_STR_STATUS_COMMENT);
	static final TextPropertyDescriptor ERROR_DESCRIPTOR = new TextPropertyDescriptor(P_ID_STATUS_ERROR, P_STR_STATUS_ERROR);
    static Vector<IPropertyDescriptor> initDescriptors(int status) {
		DESCRIPTORS = new Vector<>();
		// Status category
		DESCRIPTORS.add(getInfosDescriptor(status));
		DESCRIPTORS.add(getWarningsDescriptor(status));
		DESCRIPTORS.add(ERROR_DESCRIPTOR);
		ERROR_DESCRIPTOR.setCategory("Status");
		// Survey category
		DESCRIPTORS.add(COMMENT_DESCRIPTOR);
		COMMENT_DESCRIPTOR.setCategory("Survey");
		return DESCRIPTORS;
	}
    static Vector<IPropertyDescriptor> getDescriptors() {
    	return DESCRIPTORS;
	}
    static ComboBoxPropertyDescriptor getInfosDescriptor(int status) {
		List<String> list = new ArrayList<>();
		if ((status & SMALL_VALUE) != 0) {
			list.add("Some builds have tests with small values");
		}
		if ((status & STUDENT_TTEST) != 0) {
			list.add("Some builds have student-t test error over the threshold");
		}
		String[] infos = new String[list.size()];
		if (list.size() > 0) {
			list.toArray(infos);
		}
		ComboBoxPropertyDescriptor infoDescriptor = new ComboBoxPropertyDescriptor(P_ID_STATUS_INFO, P_STR_STATUS_INFO, infos);
		infoDescriptor.setCategory("Status");
		return infoDescriptor;
	}
    static PropertyDescriptor getWarningsDescriptor(int status) {
		List<String> list = new ArrayList<>();
		if ((status & BIG_ERROR) != 0) {
			list.add("Some builds have tests with error over 3%");
		}
		if ((status & NOT_RELIABLE) != 0) {
			list.add("Some builds have no reliable tests");
		}
		if ((status & NOT_STABLE) != 0) {
			list.add("Some builds have no stable tests");
		}
		if ((status & NO_BASELINE) != 0) {
			list.add("Some builds have no baseline to compare with");
		}
		if ((status & SINGLE_RUN) != 0) {
			list.add("Some builds have single run tests");
		}
		String[] warnings = new String[list.size()];
		if (list.size() > 0) {
			list.toArray(warnings);
		}
		ComboBoxPropertyDescriptor warningDescriptor = new ComboBoxPropertyDescriptor(P_ID_STATUS_WARNING, P_STR_STATUS_WARNING, warnings);
		warningDescriptor.setCategory("Status");
		return warningDescriptor;
	}

ResultsElement() {
}

ResultsElement(AbstractResults results, ResultsElement parent) {
    this.parent = parent;
    this.results = results;
}

ResultsElement(String name, ResultsElement parent) {
	this.parent = parent;
	this.name = name;
}

@Override
public int compareTo(ResultsElement o) {
	if (this.results == null) {
		if (o != null && this.name != null) {
			ResultsElement element = o;
			return this.name.compareTo(element.getName());
		}
		return -1;
	}
	if (o != null) {
		return this.results.compareTo(o.results);
	}
	return -1;
}

abstract ResultsElement createChild(AbstractResults testResults);

@Override
public <T> T getAdapter(Class<T> adapter) {
    if (adapter == IPropertySource.class) {
        return (T) this;
    }
    if (adapter == IWorkbenchAdapter.class) {
        return (T) this;
    }
    return null;
}

/**
 * Iterate the element children.
 */
public ResultsElement[] getChildren() {
	if (this.results == null) {
		return new ResultsElement[0];
	}
	if (this.children == null) {
		initChildren();
	}
    return this.children;
}

@Override
public Object[] getChildren(Object o) {
	if (this.results == null) {
		return new Object[0];
	}
	if (this.children == null) {
		initChildren();
	}
    return this.children;
}

@Override
public Object getEditableValue() {
    return this;
}

final String getId() {
	return getId(new StringBuffer()).toString();
}

private StringBuffer getId(StringBuffer buffer) {
	if (this.parent != null) {
		return this.parent.getId(buffer).append('/').append(getName());
	}
	return buffer.append(DB_Results.getDbName());
}

@Override
public ImageDescriptor getImageDescriptor(Object object) {
	if (object instanceof ResultsElement) {
		ResultsElement resultsElement = (ResultsElement) object;
// DEBUG
//		if (resultsElement.getName().equals("I20090806-0100")) {
//			if (resultsElement.results != null) {
//				String toString = resultsElement.results.getParent().toString();
//				String toString = resultsElement.results.toString();
//				if (toString.indexOf("testStoreExists")>0 && toString.indexOf("eplnx2")>0) {
//					System.out.println("stop");
//				}
//			}
//		}
		int elementStatus = resultsElement.getStatus();
		if (elementStatus == MISSING) {
			return HELP_IMAGE_DESCRIPTOR;
		}
		if ((elementStatus & ResultsElement.ERROR_MASK) != 0) {
			return ERROR_IMAGE_DESCRIPTOR;
		}
		if ((elementStatus & ResultsElement.WARNING_MASK) != 0) {
			return WARN_IMAGE_DESCRIPTOR;
		}
		if ((elementStatus & ResultsElement.INFO_MASK) != 0) {
			return INFO_IMAGE_DESCRIPTOR;
		}
	}
	return null;
}

@Override
public String getLabel(Object o) {
    return getName();
}

/**
 * Returns the name
 */
public String getName() {
	if (this.name == null && this.results != null) {
		this.name = this.results.getName();
	}
	return this.name;
}

/**
 * Returns the parent
 */
@Override
public Object getParent(Object o) {
    return this.parent;
}

@Override
public IPropertyDescriptor[] getPropertyDescriptors() {
	Vector<IPropertyDescriptor> descriptors = getDescriptors();
	if (descriptors == null) {
		descriptors = initDescriptors(getStatus());
	}
	int size = descriptors.size();
	IPropertyDescriptor[] descriptorsArray = new IPropertyDescriptor[size];
	descriptorsArray[0] = getInfosDescriptor(getStatus());
	descriptorsArray[1] = getWarningsDescriptor(getStatus());
	for (int i=2; i<size; i++) {
		descriptorsArray[i] = descriptors.get(i);
	}
	return descriptorsArray;
}

@Override
public Object getPropertyValue(Object propKey) {
	if (propKey.equals(P_ID_STATUS_INFO)) {
		if ((getStatus() & INFO_MASK) != 0) {
			return Integer.valueOf(0);
		}
	}
	if (propKey.equals(P_ID_STATUS_WARNING)) {
		if ((getStatus() & WARNING_MASK) != 0) {
			return Integer.valueOf(0);
		}
	}
	if (propKey.equals(P_ID_STATUS_ERROR)) {
		if ((getStatus() & BIG_DELTA) != 0) {
			return "Some builds have tests with regression";
		}
	}
	if (propKey.equals(P_ID_STATUS_COMMENT)) {
		IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(IPerformancesConstants.PLUGIN_ID);
		return preferences.get(getId(), "");
	}
	return null;
}

public ResultsElement getResultsElement(String resultName) {
	int length = getChildren(null).length;
	for (int i=0; i<length; i++) {
		ResultsElement searchedResults = this.children[i];
		if (searchedResults.getName().equals(resultName)) {
			return searchedResults;
		}
	}
	return null;
}

/**
 * Return the status of the element.
 *
 * The status is a bit mask pattern where digits are
 * allowed as follow:
 *	<ul>
 * 		<li>0-3: bits for state showing whether the element is
 * 			<ul>
 * 				<li>{@link #UNKNOWN} : not connected to a db</li>
 * 				<li>{@link #UNREAD} : is not valid (e.g. NaN results)</li>
 * 				<li>{@link #MISSING} : no results (e.g. the perf machine crashed and didn't store any results)</li>
 * 				<li>{@link #READ} : has valid results</li>
 * 			</ul>
 * 		</li>
 * 		<li>4-5: bits for information. Current possible information are
 * 			<ul>
 * 				<li>{@link #SMALL_VALUE} : build results or delta with baseline value is under 100ms</li>
 * 				<li>{@link #STUDENT_TTEST} : the Student T-test is over the threshold (old yellow color for test results)</li>
 * 			</ul>
 * 		</li>
 * 		<li>6-11: bits for warnings. Current possible warnings are
 * 			<ul>
 * 				<li>{@link #NO_BASELINE} : no baseline for the current build</li>
 * 				<li>{@link #SINGLE_RUN} : the test has only one run (i.e. no error could be computed), hence its reliability cannot be evaluated</li>
 * 				<li>{@link #BIG_ERROR} : the test result is over the 3% threshold</li>
 * 				<li>{@link #NOT_STABLE} : the test history shows a deviation between 10% and 20% (may mean that this test is not so reliable)</li>
 * 				<li>{@link #NOT_RELIABLE} : the test history shows a deviation over 20% (surely means that this test is too erratic to be reliable)</li>
 * 			</ul>
 * 		</li>
 * 		<li>12-15: bits for errors. Current possible errors are
 * 			<ul>
 * 				<li>{@link #BIG_DELTA} : the delta for the test is over the 10% threshold</li>
 * 			</ul>
 * 		</li>
 *	</ul>
 *
 * Note that these explanation applied to {@link BuildResultsElement}, and {@link DimResultsElement}.
 * For {@link ComponentResultsElement}, and {@link ScenarioResultsElement}, it's the merge of all the children status
 * and means "Some tests have..." instead of "The test has...". For {@link ConfigResultsElement}, it means the status
 * of the most recent build compared to its most recent baseline.
 *
 * @return An int with each bit set when the corresponding symptom applies.
 */
public final int getStatus() {
	if (this.status < 0) {
		initStatus();
	}
	return this.status;
}

/**
 * Return the statistics of the build along its history.
 *
 * @return An array of double built as follows:
 * <ul>
 * <li>0:	numbers of values</li>
 * <li>1:	mean of values</li>
 * <li>2:	standard deviation of these values</li>
 * <li>3:	coefficient of variation of these values</li>
 * </ul>
 */
double[] getStatistics() {
	return this.statistics;
}

/**
 * Returns whether the element (or one in its hierarchy) has an error.
 *
 * @return <code> true</code> if the element or one in its hierarchy has an error,
 * 	<code> false</code>  otherwise
 */
public final boolean hasError() {
	return (getStatus() & ERROR_MASK) != 0;
}

void initChildren() {
	AbstractResults[] resultsChildren = this.results.getChildren();
	int length = resultsChildren.length;
	this.children = new ResultsElement[length];
	int count = 0;
	for (int i=0; i<length; i++) {
		ResultsElement childElement = createChild(resultsChildren[i]);
		if (childElement != null) {
			this.children[count++] = childElement;
		}
	}
	if (count < length) {
		System.arraycopy(this.children, 0, this.children = new ResultsElement[count], 0, count);
	}
}
void initStatus() {
	this.status = READ;
	if (this.results != null) {
		if (this.children == null) initChildren();
		int length = this.children.length;
		for (int i=0; i<length; i++) {
			this.status |= this.children[i].getStatus();
		}
	}
}

int initStatus(BuildResults buildResults) {
	this.status = READ;

	// Get values
	double buildValue = buildResults.getValue();
	ConfigResults configResults = (ConfigResults) buildResults.getParent();
	BuildResults baselineResults = configResults.getBaselineBuildResults(buildResults.getName());
	double baselineValue = baselineResults.getValue();
	double delta = (baselineValue - buildValue) / baselineValue;

	// Store if there's no baseline
	if (Double.isNaN(delta)) {
		this.status |= NO_BASELINE;
	}

	// Store if there's only one run
	long baselineCount = baselineResults.getCount();
	long currentCount = buildResults.getCount();
	double error = Double.NaN;
	if (baselineCount == 1 || currentCount == 1) {
		this.status |= SINGLE_RUN;
	}

	// Store if the T-test is not good
	double ttestValue = Util.computeTTest(baselineResults, buildResults);
	int degreeOfFreedom = (int) (baselineResults.getCount()+buildResults.getCount()-2);
	if (ttestValue >= 0 && StatisticsUtil.getStudentsT(degreeOfFreedom, StatisticsUtil.T90) >= ttestValue) {
		this.status |= STUDENT_TTEST;
	}

	// Store if there's a big error (over 3%)
	double baselineError = baselineResults.getError();
	double currentError = buildResults.getError();
	error = Double.isNaN(baselineError)
			? currentError / baselineValue
			: Math.sqrt(baselineError*baselineError + currentError*currentError) / baselineValue;
	if (error > 0.03) {
		this.status |= BIG_ERROR;
	}

	// Store if there's a big delta (over 10%)
	if (delta <= -0.1) {
		this.status |= BIG_DELTA;
		double currentBuildValue = buildResults.getValue();
		double diff = Math.abs(baselineValue - currentBuildValue);
		if (currentBuildValue < 100 || diff < 100) { // moderate the status when
			// diff is less than 100ms
			this.status |= SMALL_VALUE;
		} else {
			double[] stats = getStatistics();
			if (stats != null) {
				if (stats[3] > 0.2) { // invalidate the status when the test
					// historical deviation is over 20%
					this.status |= NOT_RELIABLE;
				} else if (stats[3] > 0.1) { // moderate the status when the test
					// historical deviation is between 10%
					// and 20%
					this.status |= NOT_STABLE;
				}
			}
		}
	}

	return this.status;
}

public boolean isInitialized() {
	return this.results != null;
}

@Override
public boolean isPropertySet(Object property) {
    return false;
}

boolean onlyFingerprints() {
	if (this.parent != null) {
		return this.parent.onlyFingerprints();
	}
	return ((PerformanceResultsElement)this).fingerprints;
}

@Override
public void resetPropertyValue(Object property) {
}

void resetStatus() {
	this.status = -1;
	if (this.results != null) {
		if (this.children == null) initChildren();
		int length = this.children.length;
		for (int i=0; i<length; i++) {
			this.children[i].resetStatus();
		}
	}
}

@Override
public void setPropertyValue(Object name, Object value) {
	if (name.equals(P_ID_STATUS_COMMENT)) {
		IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(IPerformancesConstants.PLUGIN_ID);
		preferences.put(getId(), (String) value);
		try {
			preferences.flush();
		} catch (BackingStoreException e) {
			// skip
		}
	}
}

/**
 * Sets the image descriptor
 */
void setImageDescriptor(ImageDescriptor desc) {
//    this.imageDescriptor = desc;
}

@Override
public String toString() {
	if (this.results == null) {
		return getName();
	}
	return this.results.toString();
}

/*
 * Write the failures of the element in the given buffer
 */
StringBuffer getFailures(StringBuffer buffer, int kind, StringBuffer excluded) {
	int length = getChildren().length;
	for (int i=0; i<length; i++) {
		this.children[i].getFailures(buffer, kind, excluded);
	}
	return buffer;
}


}
