/*=============================================================================#
 # Copyright (c) 2019, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.rj.servi.pool;

import static org.junit.jupiter.api.Assertions.assertEquals;

import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.NullProgressMonitor;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;

import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.renv.core.BasicREnvConfiguration;
import org.eclipse.statet.rj.renv.core.BasicREnvManager;
import org.eclipse.statet.rj.renv.core.REnv;
import org.eclipse.statet.rj.renv.core.REnvConfiguration;
import org.eclipse.statet.rj.servi.RServi;


@NonNullByDefault
public abstract class AbstractServiTest {
	
	
	private static class TestREnvConfiguration extends BasicREnvConfiguration {
		
		
		public TestREnvConfiguration(final REnv rEnv, final Path stateDataRootDirectoryPath)
				throws IOException {
			super(rEnv, stateDataRootDirectoryPath);
			setFlags((LOCAL | SPEC_SETUP));
			
			final Properties p= new Properties();
			final Path propertiesFile= stateDataRootDirectoryPath.resolve("renv.properties");
			try (final BufferedReader reader= Files.newBufferedReader(propertiesFile,
					StandardCharsets.UTF_8 )) {
				p.load(reader);
			}
			load(p);
			resolvePaths();
		}
		
	}
	
	private static class TestREnvManager extends BasicREnvManager {
		
		
		private final Path basePath;
		
		
		public TestREnvManager() {
			final String pathString= nonNullAssert(System.getenv("STATET_TEST_FILES"));
			this.basePath= Path.of(pathString, "rj.rservi", "renvs");
			if (!Files.isDirectory(this.basePath)) {
				throw new RuntimeException("Configuration folder 'rj.rservi/renvs' in STATET_TEST_FILES is missing.");
			}
		}
		
		public synchronized REnv getTestREnv(final String id) throws IOException {
			REnv rEnv= get(id, null);
			if (rEnv == null) {
				rEnv= newEnv(id);
				final TestREnvConfiguration rEnvConfig= new TestREnvConfiguration(rEnv, this.basePath.resolve(id));
				addEnv(rEnvConfig);
			}
			return rEnv;
		}
		
		public REnvConfiguration getTestConfig(final String id) throws IOException {
			final REnv rEnv= getTestREnv(id);
			return nonNullAssert(rEnv.get(REnvConfiguration.class));
		}
		
	}
	
	protected static void reportErrors(final List<Throwable> errors) throws Exception {
		if (errors.isEmpty()) {
			return;
		}
		final StringBuilder sb= new StringBuilder(String.format("%1$d exception(s) occurred:", errors.size()));
		for (int i= 0; i < errors.size(); i++) {
			final Throwable e= errors.get(i);
			sb.append(String.format("\n  [%1$d] %2$s: %3$s", i, e.getClass().getName(), e.getMessage()));
		}
		throw new Exception(sb.toString(), errors.get(0));
	}
	
	
	private @Nullable TestREnvManager rEnvManager;
	
	private final List<RServi> servis= new ArrayList<>();
	
	private int testInt;
	
	
	public AbstractServiTest() throws Exception {
		ServiTests.initEnv();
	}
	
	
	protected REnvConfiguration getEnvConfiguration(final String id) throws IOException {
		TestREnvManager rEnvManager= this.rEnvManager;
		if (rEnvManager == null) {
			rEnvManager= new TestREnvManager();
			this.rEnvManager= rEnvManager;
		}
		return rEnvManager.getTestConfig(id);
	}
	
	protected void disposeServis(final List<Throwable> exceptions) {
		try {
			for (final RServi servi : this.servis) {
				try {
					servi.close();
				}
				catch (final Throwable e) {
					exceptions.add(e);
				}
			}
		}
		finally {
			this.servis.clear();
		}
	}
	
	protected void onServiGet(final RServi servi) {
		this.servis.add(servi);
	}
	
	protected void closeServi(final RServi servi) throws StatusException {
		this.servis.remove(servi);
		servi.close();
	}
	
	
	protected void assertNodeOperative(final RServi servi) throws StatusException, UnexpectedRDataException {
		final ProgressMonitor m= new NullProgressMonitor();
		final int i= this.testInt++;
		final RObject result= servi.evalData(i + "L + 1L", m);
		assertEquals(i + 1, RDataUtils.checkSingleIntValue(result));
	}
	
}
