/*=============================================================================#
 # Copyright (c) 2010, 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.internal.rhelp.core;

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

import static org.eclipse.statet.internal.rhelp.core.RHelpCoreInternals.DEBUG;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.InfoStatus;

import org.eclipse.statet.internal.rhelp.core.index.REnvIndexWriter;
import org.eclipse.statet.rhelp.core.REnvHelp;
import org.eclipse.statet.rhelp.core.REnvHelpConfiguration;
import org.eclipse.statet.rhelp.core.RHelpCore;
import org.eclipse.statet.rhelp.core.RHelpManager;
import org.eclipse.statet.rhelp.core.RPkgHelp;
import org.eclipse.statet.rj.renv.core.RPkgBuilt;


@NonNullByDefault
public class REnvHelpIndexChecker {
	
	
	private static boolean equalVersion(final RPkgBuilt pkg1, final @Nullable RPkgBuilt pkg2) {
		return (pkg2 != null
				&& pkg1.getVersion().equals(pkg2.getVersion())
				&& pkg1.getBuilt().equals(pkg2.getBuilt()) );
	}
	
	
	private final RHelpManager rHelpManager;
	
	private final REnvHelpConfiguration rEnvConfig;
	
	private int newPkg;
	private int changedPkg;
	private int newChange= -1;
	
	private Map<String, RPkgBuilt> needUpdate= new HashMap<>();
	private Map<String, RPkgBuilt> needUpdatePrevious= new HashMap<>();
	
	private @Nullable Object indexLock;
	
	private @Nullable REnvHelp rEnvHelp;
	private boolean rEnvHelpLock;
	
	private boolean inPackageCheck;
	
	
	public REnvHelpIndexChecker(final RHelpManager rHelpManager,
			final REnvHelpConfiguration rEnvConfig) {
		this.rHelpManager= nonNullAssert(rHelpManager);
		this.rEnvConfig= nonNullAssert(rEnvConfig);
		
		try {
			final Path directory= SerUtil.getIndexDirectoryPath(this.rEnvConfig);
			if (directory != null) {
				try {
					// directory writable?
					if (!isWritable(directory)) {
						if (DEBUG) {
							RHelpCoreInternals.log(new InfoStatus(RHelpCore.BUNDLE_ID,
									String.format("The index directory '%1$s' is not writable.", //$NON-NLS-1$
											directory.toString() ),
									null));
						}
						return;
					}
				}
				catch (final IOException e) {
					RHelpCoreInternals.log(new InfoStatus(RHelpCore.BUNDLE_ID,
							String.format("The index directory '%1$s' is not accessible.", //$NON-NLS-1$
									directory.toString() ),
							e));
				}
			}
		}
		catch (final Exception e) {}
	}
	
	
	private boolean isWritable(final Path directory) throws IOException {
		final Path testFile= directory.resolve("test" + System.nanoTime()); //$NON-NLS-1$
		try {
			if (!Files.isDirectory(directory)) {
				Files.createDirectories(directory);
			}
			Files.createFile(testFile);
			Files.delete(testFile);
		}
		catch (final IOException e) {
			return false;
		}
		return true;
	}
	
	
	public boolean beginCheck() {
		this.newChange= (this.newChange < 0) ? 1 : 0;
		
		if (this.rEnvConfig == null) {
			return false;
		}
		
		final REnvHelp envHelp= this.rHelpManager.getHelp(this.rEnvConfig.getREnv());
		if ((envHelp != null) ? (this.rEnvHelp == null) : this.rEnvHelp != null) {
			this.newChange= 1;
		}
		this.rEnvHelp= envHelp;
		this.rEnvHelpLock= (this.rEnvHelp != null);
		
		if (!this.rEnvConfig.equals(this.rEnvConfig.getREnv().get(REnvHelpConfiguration.class))) {
			return false;
		}
		
		this.indexLock= this.rHelpManager.beginIndexCheck(this.rEnvConfig.getREnv());
		return (this.indexLock != null);
	}
	
	public void beginPackageCheck() {
		this.inPackageCheck= true;
		
		final Map<String, RPkgBuilt> tmp= this.needUpdate;
		this.needUpdate= this.needUpdatePrevious;
		this.needUpdatePrevious= tmp;
		
		this.newPkg= 0;
		this.changedPkg= 0;
		this.newChange= 0;
	}
	
	public void checkPackage(final RPkgBuilt pkgInfo) {
		if (!REnvIndexWriter.IGNORE_PKG_NAMES.contains(pkgInfo.getName())) {
			final RPkgHelp pkgHelp= this.rEnvHelp.getPkgHelp(pkgInfo.getName());
			if (pkgHelp == null) {
				this.newPkg++;
				this.needUpdate.put(pkgInfo.getName(), pkgInfo);
				if (this.newChange == 0 && !equalVersion(pkgInfo, this.needUpdatePrevious.get(pkgInfo.getName()))) {
					this.newChange= 1;
				}
			}
			else if (!RPkgBuilt.equalsBuilt(pkgInfo, pkgHelp.getPkgDescription())) {
				this.changedPkg++;
				this.needUpdate.put(pkgInfo.getName(), pkgInfo);
				if (this.newChange == 0 && !equalVersion(pkgInfo, this.needUpdatePrevious.get(pkgInfo.getName()))) {
					this.newChange= 1;
				}
			}
		}
	}
	
	public void endPackageCheck() {
		this.inPackageCheck= false;
		
		this.needUpdatePrevious.clear();
	}
	
	public void cancelCheck() {
		if (this.inPackageCheck) {
			final Map<String, RPkgBuilt> tmp= this.needUpdate;
			this.needUpdate= this.needUpdatePrevious;
			this.needUpdatePrevious= tmp;
		}
		
		this.needUpdatePrevious.clear();
		unlock();
	}
	
	public void finalCheck() {
		unlock();
	}
	
	private void unlock() {
		if (this.rEnvHelpLock) {
			this.rEnvHelpLock= false;
			this.rEnvHelp.unlock();
		}
	}
	
	public void release() {
		if (this.indexLock != null) {
			this.rHelpManager.endIndexCheck(this.indexLock);
			this.indexLock= null;
		}
	}
	
	
	public boolean hasNewChanges() {
		return (this.newChange > 0);
	}
	
	public boolean needsComplete() {
		return (this.rEnvHelp == null);
	}
	
	public boolean hasPackageChanges() {
		return (this.newPkg > 0 || this.changedPkg > 0);
	}
	
	public int getNewPackageCount() {
		return this.newPkg;
	}
	
	public int getChangedPackageCount() {
		return this.changedPkg;
	}
	
}
