/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 *
 * Copyright 2006, 2015 Fraunhofer Gesellschaft, Munich, Germany,
 * for its Fraunhofer Institute for Computer Architecture and Software
 * Technology (FIRST), Berlin, Germany and Technical University Berlin,
 * Germany.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 *
 * Contributors:
 * Fraunhofer FIRST - Initial API and implementation
 * Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.internal.core.compiler.bytecode;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileStruct;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WeavingScheme;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;

/**
 * This class combines information about several situations where accessing
 * one element accross classes requires special treatment:
 * + decapsulation (base method accessed by role)              => OTRE removes protection
 * + callout-to-field (base field accessed by role)            => OTRE adds setter/getter
 * + base-class access -- two situations
 *     base-class decapsulation (role accesses invisible base-class) => OTRE removes protection
 *     super-base-class access (team adapts a super of a declared base-class)
 *
 * @author stephan
 */
public class OTSpecialAccessAttribute extends AbstractAttribute {
	// access kinds:
	private static final int DECAPSULATION_METHOD_ACCESS= 1;
	private static final int CALLOUT_FIELD_ACCESS = 2;
	private static final int SUPER_METHOD_ACCESS = 3;
	// OTREDyn has one more field in the attribute, use disjoint kinds:
	private static final int DYN_DECAPSULATION_METHOD_ACCESS= 4;
	private static final int DYN_CALLOUT_FIELD_ACCESS = 5;
	private static final int DYN_SUPER_METHOD_ACCESS = 6;

	/*
	 * For OTREDyn, each attribute of this type maintains a set of locally unique (per team) access IDs.
	 * These IDs are consumed and translated by OTREDyn to obtain those IDs that uniquely identify the
	 * base feature within a generated _OT$access or _OT$accessStatic method.
	 * 
	 * AccessIds are generated during resolve and stored in these AST nodes:
	 * - MethodSpec / FieldAccessSpec
	 *   - From here it is directly picked up by CallinImplementorDyn to insert
	 *     the accessId as an argument for the generated _OT$access[Static] call.
	 * - MessageSend; accessId is preset for message sends implementing decapsulating BaseAllocationExpression
	 *   - regular base class:
	 *     - detected during AllocationExpression.resolveType, throws ConstructorDecapsulationExpression
	 *     - allocation is then replaced by a MessageSend to the _OT$access method
	 *   - base is role:
	 *     - generated AST has accessId = -1 to be updated during MessageSend.resolveType() if decaps needed
	 */
	int nextAccessId = 0;
	
	/** Descriptor for a decapsulated base-method. */
	private class DecapsulatedMethodDesc {
		ReferenceBinding boundBaseclass;
		MethodBinding method;
		private int accessId;
		DecapsulatedMethodDesc(ReferenceBinding boundBaseclass, MethodBinding method) {
			this.boundBaseclass = boundBaseclass;
			this.method = method;
			if (CopyInheritance.isCreator(method))
				// creator is declared in the enclosing team
				this.boundBaseclass = this.boundBaseclass.enclosingType();
			if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
				for (DecapsulatedMethodDesc methodDesc : OTSpecialAccessAttribute.this._decapsulatedMethods) {
					if (methodDesc.method == method) {
						this.accessId = methodDesc.accessId; // share the accessId from another callout to the same method
						return;
					}
				}
				this.accessId = OTSpecialAccessAttribute.this.nextAccessId++;
			}
		}

		void write() {
			if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE)
				writeByte((byte)DYN_DECAPSULATION_METHOD_ACCESS);
			else
				writeByte((byte)DECAPSULATION_METHOD_ACCESS);
			if (this.method.isConstructor()) { // no accessor method, old style attribute
				writeName(this.method.declaringClass.attributeName());
				writeName(this.method.selector);
				writeName(this.method.signature());
			} else {
				// encode targetClass!selector(static) or targetClass?selector (virtual):
				char sep = this.method.isStatic() ? '!' : '?';
				char[] encodedName = CharOperation.concatWith(
													new char[][] {
														this.method.declaringClass.attributeName(),
														this.method.selector
													}, sep);
				char[] weaveIntoClasses = this.boundBaseclass.attributeName();
				if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
					// for OTDRE pass all classes to weave from boundBaseclass up to the actual declaring class (:-separated)
					ReferenceBinding someClass = this.boundBaseclass.getRealClass();
					if (someClass != null && TypeBinding.notEquals(someClass, this.method.declaringClass)) {
						while ((someClass = someClass.superclass()) != null) {
							weaveIntoClasses = CharOperation.concat(weaveIntoClasses, someClass.attributeName(), ':');
							if (TypeBinding.equalsEquals(someClass, this.method.declaringClass))
								break;
						}
					}
				}
				writeName(weaveIntoClasses);
				writeName(encodedName);
				writeName(this.method.signature());
			}
			if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE)
				writeUnsignedShort(this.accessId);
		}

		public String toString() {
			return new String(this.method.readableName());
		}
	}
	List<DecapsulatedMethodDesc> _decapsulatedMethods = new ArrayList<DecapsulatedMethodDesc>();

	/** Descriptor for a callout-bound base field. */
	private class CalloutToFieldDesc {
		// flags:
		private static final int CALLOUT_GET_FIELD = 0; // (== !CALLOUT_SET_FIELD)
		private static final int CALLOUT_SET_FIELD = 1;
		private static final int CALLOUT_STATIC_FIELD = 2;

		FieldBinding field;
		ReferenceBinding targetClass;
		int flags; // use the above constants
		int accessId;
		CalloutToFieldDesc(FieldBinding field, ReferenceBinding targetClass, int calloutModifier)
		{
			this.field = field;
			this.targetClass = targetClass;
			this.flags = (calloutModifier == TerminalTokens.TokenNameget) ?
							CALLOUT_GET_FIELD : CALLOUT_SET_FIELD;
			if (field.isStatic())
				this.flags |= CALLOUT_STATIC_FIELD;
			if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
				for (CalloutToFieldDesc ctf : OTSpecialAccessAttribute.this._calloutToFields) {
					if (ctf.field == field) {
						this.accessId = ctf.accessId; // share the accessId from another callout to the same field
						return;
					}
				}
				this.accessId = OTSpecialAccessAttribute.this.nextAccessId++;
			}
		}

		public int calloutModifier() {
			return ((this.flags & CALLOUT_SET_FIELD) != 0) ?
					TerminalTokens.TokenNameset :
					TerminalTokens.TokenNameget;
		}

		void write() {
			if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
				writeByte((byte)DYN_CALLOUT_FIELD_ACCESS);
				writeUnsignedShort(this.accessId);
			} else {
				writeByte((byte)CALLOUT_FIELD_ACCESS);
			}
			writeByte((byte)this.flags);
			writeName(this.targetClass.attributeName());
			writeName(this.field.name);
			writeName(this.field.type.signature());
		}

		@SuppressWarnings("nls")
		public String toString() {
			StringBuilder result = new StringBuilder();
			result.append(this.field.readableName());
			if ((this.flags & CALLOUT_GET_FIELD) != 0)
				result.append(" get");
			else
				result.append(" set");
			if ((this.flags & CALLOUT_STATIC_FIELD) != 0)
				result.append(" (static)");
			return  result.toString();
		}
	}
	List<CalloutToFieldDesc> _calloutToFields = new ArrayList<CalloutToFieldDesc>();

	/** Descriptor for base.super.m() special method access. */
	public class SuperMethodDesc
	{
		MethodBinding method;
		public SuperMethodDesc(MethodBinding method) {
			this.method = method;
		}

		void write() {
			writeByte((byte)(OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE ? DYN_SUPER_METHOD_ACCESS : SUPER_METHOD_ACCESS));
			writeName(this.method.declaringClass.attributeName());
			writeName(this.method.declaringClass.superclass().attributeName());
			writeName(this.method.selector);
			writeName(this.method.signature());
		}

		public String toString() {
			return "superaccess for "+new String(this.method.readableName()); //$NON-NLS-1$
		}


	}
	private List<SuperMethodDesc> _superMethods = new ArrayList<SuperMethodDesc>();

	private ReferenceBinding _site;

	// The following three lists are in sync (if non-null), ie., using same indices.
	/* All adapted base classes: */
	private List<ReferenceBinding> _adaptedBaseclasses = new ArrayList<ReferenceBinding>();
	/* Used only during reading, resolved types will be stored in _adaptedBaseclasses. */
	private List<char[]> _baseclassNames = null;
	/* TRUE means: use in a role referring to its decapsulated base class.
	 * FALSE means: use in a team referring to a super base class, which is indirectly adapted.*/
	private List<Boolean> _baseclassDecapsulation = new ArrayList<Boolean>();

	WeavingScheme _weavingScheme;

	public OTSpecialAccessAttribute (ReferenceBinding site, WeavingScheme weavingScheme) {
		super(IOTConstants.OTSPECIAL_ACCESS);
		this._site = site;
		this._weavingScheme = weavingScheme;
	}

	public int addDecapsulatedMethodAccess(ReferenceBinding boundBaseclass, MethodBinding method) {
		int accessId = this.nextAccessId;
		this._decapsulatedMethods.add(new DecapsulatedMethodDesc(boundBaseclass, method));
		return accessId;
	}

	public int addCalloutFieldAccess(FieldBinding field, ReferenceBinding targetClass, int calloutModifier) {
		CalloutToFieldDesc calloutToFieldDesc = new CalloutToFieldDesc(field, targetClass, calloutModifier);
		this._calloutToFields.add(calloutToFieldDesc);
		return calloutToFieldDesc.accessId;
	}

	public void addSuperMethodAccess(MethodBinding method) {
		this._superMethods.add(new SuperMethodDesc(method));
	}

	public void addBaseClassDecapsulation(ReferenceBinding baseclass) {
		for (int i=0; i<this._adaptedBaseclasses.size(); i++)
			if (this._adaptedBaseclasses.get(i).equals(baseclass)) {
				if (!this._baseclassDecapsulation.get(i).booleanValue())
					this._baseclassDecapsulation.set(i, Boolean.TRUE);
				return; // already present
			}
		this._adaptedBaseclasses.add(baseclass);
		this._baseclassDecapsulation.add(Boolean.TRUE);
	}

	public void addAdaptedBaseClass(ReferenceBinding baseclass) {
		for (int i=0; i<this._adaptedBaseclasses.size(); i++)
			if (this._adaptedBaseclasses.get(i).equals(baseclass)) {
				return; // already present
			}
		this._adaptedBaseclasses.add(baseclass.getRealType());
		this._baseclassDecapsulation.add(Boolean.FALSE);
	}

	@Override
	public void write(ClassFile classFile) {
        super.write(classFile);

        int attributeSize  = 4; // initially empty, except for two counts
        int M_SIZE = this._weavingScheme == WeavingScheme.OTDRE ? 8 : 6;
        int F_SIZE = this._weavingScheme == WeavingScheme.OTDRE ? 9 : 7;
		attributeSize += this._decapsulatedMethods.size() * (1+M_SIZE); // 1 byte kind, 3 names (+1 short for otredyn)
		attributeSize += this._calloutToFields.size() * (1+F_SIZE);		// 1 byte kind, 1 byte flags, 3 names (+1 byte for otredyn) 
		attributeSize += this._superMethods.size() * 9;        			// 1 byte kind, 4 names
		attributeSize += this._adaptedBaseclasses.size() * 3;  			// 1 name + 1 byte flag

        if (this._contentsOffset + 6 + attributeSize >= this._contents.length)
        	this._contents = classFile.getResizedContents(6 + attributeSize);

        writeName         (this._name);
        writeInt          (attributeSize);

        writeUnsignedShort(  this._decapsulatedMethods.size()
        		           + this._calloutToFields.size()
        		           + this._superMethods.size());

        for (DecapsulatedMethodDesc method : this._decapsulatedMethods)
			method.write();
        for (CalloutToFieldDesc field : this._calloutToFields)
			field.write();
        for (SuperMethodDesc method : this._superMethods)
			method.write();

		// adapted baseclasses (direct or indirect decapsulation)
        int size = this._adaptedBaseclasses.size();
        writeUnsignedShort(size);
        for (int i=0; i<size; i++) {
        	writeName(this._adaptedBaseclasses.get(i).attributeName());
        	writeByte((byte)(this._baseclassDecapsulation.get(i).booleanValue()?1:0));
        }
        writeBack(classFile);
	}


    /**
     * Read the attribute from byte code.
     *
	 * @param reader
	 * @param readOffset
	 * @param constantPoolOffsets
	 */
	public OTSpecialAccessAttribute(ClassFileStruct reader, int readOffset, int[] constantPoolOffsets) {
		super(IOTConstants.OTSPECIAL_ACCESS);
		this._reader = reader;
		this._readOffset = readOffset;
		this._constantPoolOffsets = constantPoolOffsets;

		int count = consumeShort();
		for (int i=0; i<count; i++)
			readElement();

		count = consumeShort();
		this._baseclassNames = new ArrayList<char[]>(count);
		for (int i=0; i<count; i++) {
			this._baseclassNames.add(consumeName());
			this._baseclassDecapsulation.add(consumeByte()==1?Boolean.TRUE:Boolean.FALSE);
		}
	}

	private void readElement() {
		int kind = consumeByte();
		switch(kind) {
		case DYN_DECAPSULATION_METHOD_ACCESS:
			this._readOffset += 2; // extra id
				//$FALL-THROUGH$
		case DECAPSULATION_METHOD_ACCESS:
			this._readOffset += 6;
			break;
		case DYN_CALLOUT_FIELD_ACCESS:
			this._readOffset += 2; // extra id
				//$FALL-THROUGH$
		case CALLOUT_FIELD_ACCESS:
			this._readOffset += 7;
			break;
		case DYN_SUPER_METHOD_ACCESS:
		case SUPER_METHOD_ACCESS:
			this._readOffset += 8;
			break;
		}

	}

	@Override
	public void evaluate(Binding binding, LookupEnvironment environment, char[][][] missingTypeNames) {
		checkBindingMismatch(binding, 0);
		this._site = (ReferenceBinding)binding;
		// don't see a need to evaluate all this:
//		for (TeamFieldDesc field : _teamFields)
//			field.evaluate(binding, environment);
		if (((ReferenceBinding)binding).isRole())
			((ReferenceBinding)binding).roleModel.setSpecialAccess(this);
		if (this._baseclassNames != null)
			for (int i=0; i<this._baseclassNames.size(); i++) {
				char[] name = this._baseclassNames.get(i);
				if (name != null && name.length > 0)
					if (this._baseclassDecapsulation.get(i).booleanValue())
						this._adaptedBaseclasses.add(environment.getTypeFromConstantPoolName(name, 0, -1, false, missingTypeNames));
			}
	}

	/**
	 * Add the field accesses of this attribute to the given sub team.
	 * @deprecated This method is not finished!
	 */
	@Deprecated()
	public void addFieldAccessesTo(TeamModel subTeam) {
		if (this._calloutToFields != null) {
			// FIXME(SH): need to evaluate _calloutToFields from byte code!
			for (CalloutToFieldDesc fieldDesc : this._calloutToFields) {
				ReferenceBinding oldBase = fieldDesc.field.declaringClass;
				for(RoleModel role : subTeam.getRoles(false)) {
					ReferenceBinding newBase = role.getBaseTypeBinding();
					if (newBase == null)
						continue;  // current role is not relevant (not bound)
					if (!CharOperation.equals(newBase.sourceName(), oldBase.sourceName()))
						continue;  // current role is bound to a different base
					if (newBase.isRoleType()) {
						if (newBase instanceof WeakenedTypeBinding)
							newBase = ((WeakenedTypeBinding)newBase).getStrongType();
						if (((RoleTypeBinding)newBase)._teamAnchor.isBaseAnchor()) {
							FieldBinding newField = newBase.getRealClass().getField(fieldDesc.field.name, false);
							role.addAccessedBaseField(newField, fieldDesc.calloutModifier());
						}
					}
				}
			}
		}

	}

	@SuppressWarnings("nls")
	@Override
	public String toString() {
		StringBuilder result = new StringBuilder();
		result.append(this._site.readableName());
		result.append(" requires special access to these elements:");
		for (DecapsulatedMethodDesc method : this._decapsulatedMethods) {
			result.append("\n\tmethod ");
			result.append(method.toString());
		}
		for (CalloutToFieldDesc field : this._calloutToFields) {
			result.append("\n\tfield ");
			result.append(field.toString());
		}
		for (SuperMethodDesc method : this._superMethods) {
			result.append("\n\t");
			result.append(method.toString());
		}
		for (ReferenceBinding baseclass : this._adaptedBaseclasses) {
			result.append("\n\tbase class ");
			result.append(baseclass.readableName());
		}
		return result.toString();
	}

}
