/*=============================================================================#
 # Copyright (c) 2009, 2021 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.ltk.model.core.element.LtkModelElementFilter;
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.RElement;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.core.model.RFrame;
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, RFrame {
	
	
	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= RFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_PACKAGE, "base")); //$NON-NLS-1$
			}
			return;
		case ENVTYPE_AUTOLOADS:
			this.environmentName= ENVNAME_AUTOLOADS;
			this.frameType= RFrame.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= RFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_PACKAGE, envName.substring(8)));
			}
			return;
		case ENVTYPE_GLOBAL:
			this.environmentName= ENVNAME_GLOBAL;
			this.frameType= RFrame.PROJECT;
			if (getElementName() == null) {
				setElementName(RModel.GLOBAL_ENV_NAME);
			}
			return;
		case ENVTYPE_EMTPY:
			this.environmentName= ENVNAME_EMPTY;
			this.frameType= RFrame.EXPLICIT;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.MAIN_OTHER, ENVNAME_EMPTY));
			}
			return;
		case ENVTYPE_NAMESPACE:
			assert (envName != null);
			this.environmentName= envName;
			this.frameType= RFrame.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= RFrame.PACKAGE;
			if (getElementName() == null) {
				setElementName(RElementName.create(RElementName.SCOPE_NS, envName));
			}
			return;
		default:
			this.environmentName= envName;
			this.frameType= RFrame.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 LtkModelElementFilter 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 LtkModelElementFilter 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 == RFrame.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 RElement> getModelElements() {
		return null;
	}
	
	@Override
	public @Nullable List<? extends RFrame> 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();
	}
	
}
