/*=============================================================================#
 # Copyright (c) 2017, 2019 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.server.rh;

import static org.eclipse.statet.rj.server.rh.ObjectManager.NO_REF;
import static org.eclipse.statet.rj.server.rh.ObjectManager.STRONG_REF;
import static org.eclipse.statet.rj.server.rh.ObjectManager.WEAK_REF;

import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Set;

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


/**
 * R environment.
 */
@NonNullByDefault
public final class RhEnv {
	
	
	private static final Object NO_DATA= new Object();
	
	
	public final Handle handle;
	
	private boolean isDisposed;
	
	private final RhEngine engine;
	
	private final @Nullable RhRefListener refListener;
	private int strongCounter;
	private int weakCounter;
	private @Nullable RhWeakRef weakRef;
	
	
	private final IdentityHashMap<String, @Nullable Object> regKeys= new IdentityHashMap<>(4);
	
	
	public RhEnv(final RhEngine engine, final Handle handle,
			 final @Nullable RhRefListener refListener) {
		this.engine= engine;
		this.handle= handle;
		this.refListener= refListener;
	}
	
	
	public boolean isRegAny() {
		return (this.regKeys.size() > 0);
	}
	
	public boolean isReg(final String key) {
		return this.regKeys.containsKey(key);
	}
	
	public boolean isRegAny(final Collection<String> keys) {
		final Set<String> keySet= this.regKeys.keySet();
		for (final String key : keys) {
			if (keySet.contains(key)) {
				return true;
			}
		}
		return false;
	}
	
	
	public boolean addReg(final String key) {
		if (!this.regKeys.containsKey(key)) {
			this.regKeys.put(key, NO_DATA);
			
			if (!this.isDisposed) {
				switch (key.charAt(1)) {
				case STRONG_REF:
					preserveStrong();
					break;
				case WEAK_REF:
					preserveWeak();
					break;
				default:
					break;
				}
			}
			
			return true;
		}
		return false;
	}
	
	public boolean addReg(final String key, final Object data) {
		if (this.regKeys.put(key, data) == null) {
			if (!this.isDisposed) {
				switch (key.charAt(1)) {
				case STRONG_REF:
					preserveStrong();
					break;
				case WEAK_REF:
					preserveWeak();
					break;
				default:
					break;
				}
			}
			
			return true;
		}
		return false;
	}
	
	public @Nullable Object getData(final String key) {
		final Object object= this.regKeys.get(key);
		return (object != NO_DATA) ? object : null;
	}
	
	public boolean removeReg(final String key) {
		if (this.regKeys.remove(key) != null) {
			
			if (!this.isDisposed) {
				switch (key.charAt(1)) {
				case STRONG_REF:
					releaseStrong();
					break;
				case WEAK_REF:
					releaseWeak();
					break;
				default:
					break;
				}
			}
			
			return true;
		}
		return false;
	}
	
	
	private void checkWeakRef() {
		if (this.weakCounter > 0 && this.strongCounter == 0 && this.weakRef == null) {
			this.weakRef= this.engine.newWeakRef(this.handle, (this.refListener != null) ?
					this.refListener :
					(final RhRef ref) -> dispose() );
		}
	}
	
	private void preserveStrong() {
		if (this.strongCounter++ == 0) {
			this.engine.preserve(this.handle);
		}
	}
	
	private void releaseStrong() {
		if (--this.strongCounter == 0) {
			checkWeakRef();
			this.engine.releasePreserved(this.handle);
		}
	}
	
	private void preserveWeak() {
		if (this.weakCounter++ == 0) {
			checkWeakRef();
		}
	}
	
	private void releaseWeak() {
		--this.weakCounter;
	}
	
	
	public boolean isDisposed() {
		return this.isDisposed;
	}
	
	protected void dispose() {
		if (this.isDisposed) {
			return;
		}
		
		this.isDisposed= true;
		if (this.weakRef != null) {
			this.weakRef.dispose(this.engine);
		}
		if (this.strongCounter > 0) {
			this.strongCounter= 0;
			this.engine.releasePreserved(this.handle);
		}
	}
	
	
	@Override
	public String toString() {
		final StringBuilder sb= new StringBuilder("env ");
		sb.append(this.handle.toString());
		sb.append(" (");
		if (this.isDisposed) {
			sb.append("disposed, ");
		}
		if (this.strongCounter > 0) {
			sb.append("r= " + STRONG_REF);
		}
		else if (this.weakRef != null) {
			sb.append("r= " + WEAK_REF);
		}
		else {
			sb.append("r= " + NO_REF);
		}
		sb.append(')');
		return sb.toString();
	}
	
}
