/*=============================================================================#
 # Copyright (c) 2009, 2018 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.r.rdata;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.r.console.core.RProcess;
import org.eclipse.statet.r.console.core.RProcessREnvironment;
import org.eclipse.statet.r.core.data.CombinedRElement;
import org.eclipse.statet.r.core.model.IRElement;
import org.eclipse.statet.r.core.model.IRFrame;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.rj.data.RCharacterStore;
import org.eclipse.statet.rj.data.REnvironment;
import org.eclipse.statet.rj.data.RJIO;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RObjectFactory;
import org.eclipse.statet.rj.data.RStore;
import org.eclipse.statet.rj.data.impl.ExternalizableRObject;
import org.eclipse.statet.rj.data.impl.RCharacter32Store;


public final class REnvironmentVar extends BasicCombinedRElement
		implements REnvironment, RProcessREnvironment, ExternalizableRObject, IRFrame {
	
	
	private String className1;
	
	private String environmentName;
	private String combinedName;
	private int specialType;
	private long handle;
	
	private int length;
	private BasicCombinedRElement[] components;
	
	private RCharacter32Store namesAttribute;
	
	private int frameType;
	
	private RProcess source;
	private int stamp;
	private int loadOptions;
	
	
	public REnvironmentVar(final String envName, final boolean isSearch,
			final @Nullable BasicCombinedRElement parent, final @Nullable RElementName name) {
		super(parent, name);
		
		if (envName != null) {
			if (envName.equals("base") || envName.equals("package:base")) { //$NON-NLS-1$ //$NON-NLS-2$
				this.specialType= ENVTYPE_BASE;
			}
			else if (envName.startsWith("package:")) { //$NON-NLS-1$
				this.specialType= ENVTYPE_PACKAGE;
			}
			else if (envName.equals(".GlobalEnv") || envName.equals("R_GlobalEnv")) { //$NON-NLS-1$ //$NON-NLS-2$
				this.specialType= ENVTYPE_GLOBAL;
			}
			else if (envName.equals("Autoloads")) { //$NON-NLS-1$
				this.specialType= ENVTYPE_AUTOLOADS;
			}
		}
		setEnvName(envName, isSearch);
	}
	
	public REnvironmentVar(
			final int specialType, final String envName,
			final @Nullable BasicCombinedRElement parent, final RElementName name,
			final int length, final BasicCombinedRElement[] components, final RCharacter32Store names) {
		super(parent, name);
		
		this.specialType= specialType;
		setEnvName(envName, false);
		
		this.length= length;
		this.components= components;
		this.namesAttribute= names;
	}
	
	public REnvironmentVar(final RJIO io, final CombinedFactory factory,
			final @Nullable BasicCombinedRElement parent, final @Nullable RElementName name)
			throws IOException {
		super(parent, name);
		
		//-- options
		final int options= io.readInt();
		//-- special attributes
		this.specialType= (byte) ((options >>> 24) & 0xff);
		this.className1= ((options & RObjectFactory.O_CLASS_NAME) != 0) ?
				io.readString() : RObject.CLASSNAME_ENVIRONMENT;
		//-- data
		this.handle= io.readLong();
		setEnvName(io.readString(), false);
		final int l= this.length= (int) io.readVULong((byte) (options & RObjectFactory.O_LENGTHGRADE_MASK));
		
		if ((options & RObjectFactory.O_NO_CHILDREN) != 0) {
			this.namesAttribute= null;
			this.components= null;
		}
		else {
			this.namesAttribute= new RCharacter32Store(io, l);
			this.components= new BasicCombinedRElement[l];
			for (int i= 0; i < l; i++) {
				this.components[i]= factory.readObject(io, this,
						RElementName.create(RElementName.MAIN_DEFAULT, this.namesAttribute.getChar(i)) );
			}
		}
		
		if (getElementName() == null) {
			final String envName= getEnvironmentName();
			setElementName(RElementName.create(RElementName.MAIN_OTHER,
					(envName != null) ? envName : "" )); //$NON-NLS-1$
		}
	}
	
	@Override
	public void writeExternal(final RJIO io, final RObjectFactory factory) throws IOException {
		final int l= this.length;
		//-- options
		int options= io.getVULongGrade(l);
		options|= (this.specialType << 24);
		final boolean customClass= !this.className1.equals(RObject.CLASSNAME_ENVIRONMENT);
		if (customClass) {
			options |= RObjectFactory.O_CLASS_NAME;
		}
		if (this.components == null) {
			options |= RObjectFactory.O_NO_CHILDREN;
		}
		io.writeInt(options);
		//-- special attributes
		if (customClass) {
			io.writeString(this.className1);
		}
		
		io.writeLong(this.handle);
		io.writeString(this.combinedName);
		io.writeVULong((byte) (options & RObjectFactory.O_LENGTHGRADE_MASK), l);
		
		if (this.components != null) {
			this.namesAttribute.writeExternal(io);
			//-- data
			for (int i= 0; i < this.length; i++) {
				factory.writeObject(this.components[i], io);
			}
		}
	}
	
	public void setSource(final RProcess source, final int stamp, final int loadOptions) {
		this.source= source;
		this.stamp= stamp;
		this.loadOptions= loadOptions;
	}
	
	@Override
	public RProcess getSource() {
		return this.source;
	}
	
	@Override
	public int getStamp() {
		return this.stamp;
	}
	
	public int getLoadOptions() {
		return this.loadOptions;
	}
	
	
	protected void setEnvName(final String envName, final boolean isSearch) {
		switch (this.specialType) {
		case ENVTYPE_BASE:
			this.environmentName= ENVNAME_BASE;
			this.frameType= IRFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_PACKAGE, "base")); //$NON-NLS-1$
			}
			return;
		case ENVTYPE_AUTOLOADS:
			this.environmentName= ENVNAME_AUTOLOADS;
			this.frameType= IRFrame.EXPLICIT;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_SEARCH_ENV, ENVNAME_AUTOLOADS));
			}
			return;
		case ENVTYPE_PACKAGE:
			assert (envName != null && envName.startsWith("package:")); //$NON-NLS-1$
			this.environmentName= envName;
			this.frameType= IRFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_PACKAGE, envName.substring(8)));
			}
			return;
		case ENVTYPE_GLOBAL:
			this.environmentName= ENVNAME_GLOBAL;
			this.frameType= IRFrame.PROJECT;
			if (getElementName() == null) {
				setElementName(RModel.GLOBAL_ENV_NAME);
			}
			return;
		case ENVTYPE_EMTPY:
			this.environmentName= ENVNAME_EMPTY;
			this.frameType= IRFrame.EXPLICIT;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.MAIN_OTHER, ENVNAME_EMPTY));
			}
			return;
		case ENVTYPE_NAMESPACE:
			assert (envName != null);
			this.environmentName= envName;
			this.frameType= IRFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_NS_INT, envName));
			}
			return;
		case ENVTYPE_NAMESPACE_EXPORTS:
			assert (envName != null);
			this.environmentName= envName;
			this.frameType= IRFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_NS, envName));
			}
			return;
		default:
			this.environmentName= envName;
			this.frameType= IRFrame.EXPLICIT;
			if (getElementName() == null) {
				setElementName(RElementName.create(
						(isSearch) ? RElementName.SCOPE_SEARCH_ENV : RElementName.MAIN_OTHER,
						envName ));
			}
			return;
		}
	}
	
	
	@Override
	public final byte getRObjectType() {
		return TYPE_ENVIRONMENT;
	}
	
	@Override
	public String getRClassName() {
		return this.className1;
	}
	
	
	@Override
	public int getSpecialType() {
		return this.specialType;
	}
	
	@Override
	public String getEnvironmentName() {
		return this.environmentName;
	}
	
	@Override
	public long getHandle() {
		return this.handle;
	}
	
	
	@Override
	public long getLength() {
		return this.length;
	}
	
	@Override
	public RCharacterStore getNames() {
		return this.namesAttribute;
	}
	
	@Override
	public String getName(final int idx) {
		return this.namesAttribute.getChar(idx);
	}
	
	@Override
	public String getName(final long idx) {
		return this.namesAttribute.getChar(idx);
	}
	
	@Override
	public @Nullable CombinedRElement get(final int idx) {
		return this.components[idx];
	}
	
	@Override
	public @Nullable CombinedRElement get(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return this.components[(int) idx];
	}
	
	@Override
	public @Nullable CombinedRElement get(final String name) {
		final int idx= this.namesAttribute.indexOf(name, 0);
		if (idx >= 0) {
			return this.components[idx];
		}
		return null;
	}
	
	@Override
	public @Nullable RStore<?> getData() {
		return null;
	}
	
	
	@Override
	public int getElementType() {
		return R_GENERAL_VARIABLE;
	}
	
	
	@Override
	public boolean hasModelChildren(final @Nullable Filter filter) {
		if (this.components == null) {
			return false;
		}
		if (filter == null) {
			return (this.components.length > 0);
		}
		else {
			for (final BasicCombinedRElement component : this.components) {
				if (filter.include(component)) {
					return true;
				}
			}
			return false;
		}
	}
	
	@Override
	public List<? extends CombinedRElement> getModelChildren(final @Nullable Filter filter) {
		if (this.components == null) {
			return Collections.emptyList();
		}
		if (filter == null) {
			return ImCollections.newList(this.components);
		}
		else {
			final List<BasicCombinedRElement> list= new ArrayList<>();
			for (final BasicCombinedRElement component : this.components) {
				if (filter.include(component)) {
					list.add(component);
				}
			}
			return list;
		}
	}
	
	
	@Override
	public int getFrameType() {
		return this.frameType;
	}
	
	public boolean containsElement(final String name) {
		return this.namesAttribute.contains(name);
	}
	
	
	@Override
	@SuppressWarnings("unchecked")
	public <T> @Nullable T getAdapter(final Class<T> adapterType) {
		if (adapterType == IRFrame.class) {
			return (T) this;
		}
		return super.getAdapter(adapterType);
	}
	
	public void setError(final String message) {
		setElementName(RElementName.create(RElementName.MAIN_OTHER, this.environmentName));
		this.components= new BasicCombinedRElement[0];
		this.namesAttribute= new RCharacter32Store();
		this.combinedName= this.combinedName + " ("+message+")"; //$NON-NLS-1$ //$NON-NLS-2$
	}
	
	
	@Override
	public @Nullable String getFrameId() {
		return null;
	}
	
	@Override
	public @Nullable List<? extends IRElement> getModelElements() {
		return null;
	}
	
	@Override
	public @Nullable List<? extends IRFrame> getPotentialParents() {
		return null;
	}
	
	
	@Override
	protected int singleHash() {
		return (this.specialType > 0 && this.environmentName != null) ?
				this.environmentName.hashCode() : (int) this.handle;
	}
	
	@Override
	public boolean equals(final @Nullable Object obj) {
		if (obj == this) {
			return true;
		}
		if (obj instanceof REnvironment) {
			final REnvironment other= (REnvironment) obj;
			return (this.specialType == other.getSpecialType()
					&& Objects.equals(this.environmentName, other.getEnvironmentName()) );
		}
		return false;
	}
	
	
	@Override
	public String toString() {
		final StringBuilder sb= new StringBuilder();
		sb.append("RObject type=environment, class=").append(getRClassName());
		sb.append("\n\tlength=").append(this.length);
		if (this.components != null) {
			sb.append("\n\tdata: ");
			for (int i= 0; i < this.length; i++) {
				sb.append("\n$").append(this.namesAttribute.getChar(i)).append("\n");
				sb.append(this.components[i]);
			}
		}
		else {
			sb.append("\n<NODATA/>");
		}
		return sb.toString();
	}
	
}
