/**********************************************************************
 * This file is part of "Object Teams Dynamic Runtime Environment"
 * 
 * Copyright 2009, 2015 Oliver Frank and others.
 * 
 * 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:
 *		Oliver Frank - Initial API and implementation
 *		Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otredyn.bytecode.asm;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;
import org.eclipse.objectteams.otredyn.bytecode.Field;
import org.eclipse.objectteams.otredyn.bytecode.IBytecodeProvider;
import org.eclipse.objectteams.otredyn.bytecode.Method;
import org.eclipse.objectteams.otredyn.bytecode.RedefineStrategyFactory;
import org.eclipse.objectteams.otredyn.runtime.TeamManager;
import org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer;
import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;
import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
 * This class implements the bytecode manipulating part of {@link AbstractBoundClass}.
 * It uses ASM to manipulate the bytecode.
 * @author Oliver Frank
 */
class AsmWritableBoundClass extends AsmBoundClass {
	private static boolean dumping = false;

    static {
        if(System.getProperty("ot.dump")!=null)
            dumping = true;
    }
    
	private ClassWriter writer;
	private MultiClassAdapter multiAdapter;
	private ClassReader reader;
	private boolean isTransformed;
	private boolean isTransformedForMemberAccess;
	private boolean isTransformedStatic;
	private List<AbstractTransformableClassNode> nodes;
	private boolean isFirstTransformation = true;

	private boolean isTransformationActive;

	protected AsmWritableBoundClass(String name, String id, IBytecodeProvider bytecodeProvider, ClassLoader loader) {
		super(name, id, bytecodeProvider, loader);
	}
	
	/**
	 * Adds a field to the class
	 * 
	 * @param field defines name and type of the field
	 * @param access access flags for the field
	 * @see AddFieldAdapter
	 */
	private void addField(Field field, int access) {
		assert (isTransformationActive) : "No transformation active";
		String desc = field.getSignature();
		multiAdapter.addVisitor(new AddFieldAdapter(writer, field.getName(), access, desc));
	}

	/**
	 * Adds an empty method to the class
	 * @param method
	 * @param access
	 * @param signature
	 * @param exceptions
	 * @param superToCall may be null, else the super class to which a super-call should be inserted
	 * @see AddEmptyMethodAdapter
	 */
	private void addEmptyMethod(Method method, int access, String signature, String[] exceptions, String superToCall) {
		assert (isTransformationActive) : "No transformation active";
		String desc = method.getSignature();
		Type[] args = Type.getArgumentTypes(desc);
		multiAdapter.addVisitor(new AddEmptyMethodAdapter(writer, method.getName(),
				access, desc, exceptions, signature, args.length + 1, superToCall));
	}

	/**
	 * Adds an interface to the class
	 * @see AddInterfaceAdapter
	 * @param name
	 */
	private void addInterface(String name) {
		assert (isTransformationActive) : "No transformation active";
		multiAdapter.setToplevelVisitor(new AddInterfaceAdapter(writer, name));
	}

	/**
	 * This method must be called before any transformation
	 * can be done. It makes it possible to collect all transformations
	 * and transform the bytecode only one time at the end.
	 */
	@Override
	protected void startTransformation() {
		
		reader = new ClassReader(allocateAndGetBytecode());

		writer = getClassWriter();
		multiAdapter = new MultiClassAdapter(writer);
		nodes = new ArrayList<AbstractTransformableClassNode>();
		isTransformationActive = true;
	}

	LoaderAwareClassWriter getClassWriter() {
		int flags = ClassWriter.COMPUTE_FRAMES;
// DEBUG: when frame computation throws an exception, enable dumping of class file without frames computed:
//		if (getName().contains("JUnitLaunchConfigurationDelegate"))
//			flags = 0;
		return new LoaderAwareClassWriter(reader, flags, this.loader);
	}
	
	/**
	 * Is the class manipulated right now.
	 */
	@Override
	public boolean isTransformationActive() {
		return isTransformationActive;
	}

	/**
	 * Executes all pending transformations.
	 */
	@Override
	protected void endTransformation() {
		assert (isTransformationActive) : "No transformation active";
		
		if (multiAdapter.hasVisitors() || !nodes.isEmpty()) {
			// //TODO (ofra): Do everything in one transformation
			// Do all transformation with the Core API of ASM
//			try {
				reader.accept(multiAdapter, ClassReader.SKIP_FRAMES);
//			} catch (RuntimeException e) {
//				System.err.println("Cannot transform class "+this+":");
//				e.printStackTrace();
//				return;
//			}
			setBytecode(writer.toByteArray());
			//Do all transformations with the Tree API of ASM
			for (AbstractTransformableClassNode node : nodes) {
				reader = new ClassReader(allocateAndGetBytecode());
				reader.accept(node, ClassReader.SKIP_FRAMES);
				if (node.transform()) {
					writer = getClassWriter();
					node.accept(writer);
					setBytecode(writer.toByteArray());
				}
			}
			
			dump();
			reader = null;
			writer = null;
			multiAdapter = null;
			nodes = null;
			//Check, if this is the first transformation for this class
			if (!this.isFirstTransformation) {
				// It is not the first transformation, so redefine the class
				try {
					redefine();
				} catch (Throwable t) {
	//				t.printStackTrace(System.out);
					// if redefinition failed (ClassCircularity?) install a runnable for deferred redefinition:
					final Runnable previousTask = TeamManager.pendingTasks.get();
					TeamManager.pendingTasks.set(new Runnable() {
						public void run() {
							if (previousTask != null)
								previousTask.run();
							redefine();
						}
						@Override
						public String toString() {
							return "Retry "+AsmWritableBoundClass.this.toString();
						}
					});
					// not done, only partial cleanup:
					isTransformationActive = false;
					isFirstTransformation = false;
					return;
				}
			}
		} else {
			reader = null;
			writer = null;
			multiAdapter = null;
			nodes = null;
		}
		isTransformationActive = false;
		isFirstTransformation = false;
		releaseBytecode();
	}

	/**
	 * Creates the dispatch code in the original method.
	 * @see CreateDispatchCodeInOrgMethodAdapter
	 */
	@Override
	protected void createDispatchCodeInOrgMethod(Method boundMethod,
			int joinPointId, int boundMethodId) {
		assert (isTransformationActive) : "No transformation active";
		nodes.add(new CreateDispatchCodeInOrgMethodAdapter(boundMethod,
				joinPointId, boundMethodId));
	}

	/**
	 * Creates the dispatch code in the method callAllBindings.
	 * @see CreateDispatchCodeInCallAllBindingsAdapter
	 */
	@Override
	protected void createDispatchCodeInCallAllBindings(int joinpointId,
			int boundMethodId) {
		assert (isTransformationActive) : "No transformation active";
		nodes.add(new CreateDispatchCodeInCallAllBindingsAdapter(joinpointId,
				boundMethodId));
	}

	/**
	 * Moves the code of the original method to callOrig or callOrigStatic.
	 * @see MoveCodeToCallOrigAdapter
	 */
	@Override
	protected void moveCodeToCallOrig(Method boundMethod, int boundMethodId) {
		if (boundMethod.getName().equals("<init>")) return; // don't move constructor code
		assert (isTransformationActive) : "No transformation active";
		nodes.add(new MoveCodeToCallOrigAdapter(this, boundMethod, boundMethodId, this.weavingContext));
	}
	
	/**
	 * Creates a super call in callOrig.
	 * @see CreateSuperCallInCallOrigAdapter
	 */
	@Override
	protected void createSuperCallInCallOrig(int joinpointId) {
		assert (isTransformationActive) : "No transformation active";
		nodes.add(new CreateSuperCallInCallOrigAdapter(
				getInternalSuperClassName(), joinpointId));

	}

	/**
	 * Creates a call of callAllBindings in the original method.
	 * @see CreateCallAllBindingsCallInOrgMethod
	 */
	@Override
	protected void createCallAllBindingsCallInOrgMethod(Method boundMethod,
			int boundMethodId, boolean needToAddMethod) {
		assert (isTransformationActive) : "No transformation active";
		if (needToAddMethod) {
			String desc = boundMethod.getSignature();
			Type[] args = Type.getArgumentTypes(desc);
			multiAdapter.addVisitor(new AddEmptyMethodAdapter(writer, boundMethod.getName(),
					boundMethod.getAccessFlags(), desc, null, boundMethod.getSignature(), args.length+1/*maxLocals*/, null));
		}
		nodes.add(new CreateCallAllBindingsCallInOrgMethod(boundMethod,
				boundMethodId));

	}

	/**
	 * Prepares a the class for a decapsulation of one of its methods
	 */
	@Override
	protected void weaveMethodAccess(Method method, int accessId) {
		nodes.add(new CreateMethodAccessAdapter(method, accessId));

	}

	/**
	 * Prepares a the class for a decapsulation of one of its fields
	 */
	@Override
	protected void weaveFieldAccess(Field field, int accessId) {
		nodes.add(new CreateFieldAccessAdapter(field, accessId));

	}

	/**
	 * Write the bytecode in the directory ./otdyn to the hard disk, 
	 * if the system property "ot.dump" is set.
	 */
	private void dump() {
		if (!dumping)
			return;
		
		FileOutputStream fos = null;
		try {
			String name = getName();
			int index = name.indexOf('/');
			if (index == -1)
				index = name.indexOf('.');
			File dir = new File("otdyn");
			if (!dir.exists())
				dir.mkdir();
			String filename = "otdyn/" + name.substring(index + 1) + ".class";
			fos = new FileOutputStream(filename);
			fos.write(allocateAndGetBytecode());
			fos.close();
		} catch (Exception e) {
			// TODO (ofra): Log error while dumping
			e.printStackTrace();
		} 
	}

	private int n = 0; // counts dump files for this class
	public void dump(byte[] bytecode, String postfix) {
		if (!dumping)
			return;

		FileOutputStream fos = null;
		try {
			String name = getName();
			int index = name.indexOf('/');
			if (index == -1)
				index = name.indexOf('.');
			File dir = new File("otdyn");
			if (!dir.exists())
				dir.mkdir();
			String filename = "otdyn/" + name.substring(index + 1) + postfix+".#"+(n++);
			fos = new FileOutputStream(filename);
			fos.write(bytecode);
			fos.close();
		} catch (Exception e) {
			// TODO (ofra): Log error while dumping
			e.printStackTrace();
		}
	}

	/**
	 * Redefines the class
	 */
	private void redefine() {
		try {
			Class<?> clazz = this.loader.loadClass(this.getName()); // boot classes may have null classloader, can't be redefined anyway?
			byte[] bytecode = allocateAndGetBytecode();
			dump(bytecode, "redef");
			RedefineStrategyFactory.getRedefineStrategy().redefine(clazz, bytecode);
		} catch (Throwable t) {
			throw new RuntimeException("Error occured while dynamically redefining class " + getName()+"\n"+t.getMessage(), t);
		}
	}

	/**
	 * Do all transformations needed at load time
	 */
	@Override
	protected void prepareAsPossibleBaseClass() {
		if (!isFirstTransformation)
			return;

		addInterface(ClassNames.I_BOUND_BASE_SLASH);
		
		int methodModifiers = Opcodes.ACC_PUBLIC;
		if (isInterface())
			methodModifiers |= Opcodes.ACC_ABSTRACT;
		
		if (!isInterface())
			addField(ConstantMembers.roleSet, Opcodes.ACC_PUBLIC);
		
		addEmptyMethod(ConstantMembers.callOrig, methodModifiers, null, null, null);
		addEmptyMethod(ConstantMembers.callAllBindingsClient, methodModifiers, null, null, null);
		
		// the methods callOrigStatic and accessStatic have to already exist to call it in a concrete team
		if (!isInterface()) {
			addEmptyMethod(getCallOrigStatic(), Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, null, null, null);
			addEmptyMethod(ConstantMembers.accessStatic, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, null, null, null);
		}
		
		String superClassName = getSuperClassName().replace('.', '/');
		if (!ObjectTeamsTransformer.isWeavable(superClassName))
			superClassName = null;
		addEmptyMethod(ConstantMembers.access, methodModifiers, null, null, superClassName);
		addEmptyMethod(ConstantMembers.addOrRemoveRole, methodModifiers, null, null, null);
		
		if (!isInterface())
			multiAdapter.addVisitor(new AddAfterClassLoadingHook(this.writer, this));

		if (AddThreadNotificationAdapter.shouldNotify(this))
			multiAdapter.addVisitor(new AddThreadNotificationAdapter(this.writer, this));
	}

	/** Get the suitable variant of _OT$callOrigStatic, respecting synth args for static role methods. */
	Method getCallOrigStatic() {
		if (isRole())
			return ConstantMembers.callOrigStaticRoleVersion(getEnclosingClassName());
		else
			return ConstantMembers.callOrigStatic;
	}

	/**
	 * Prepares the class for implicit team activation by adding appropriate calls to
	 * _OT$implicitlyActivate(), _OT$implicitlyDeactivate() into all relevant methods.
	 */
	@Override
	protected void prepareTeamActivation() {
		if (!isFirstTransformation || isInterface())
			return;
		if (isTeam() || isRole())
			multiAdapter.addVisitor(new AddImplicitActivationAdapter(this.writer, this));
		AddGlobalTeamActivationAdapter.checkAddVisitor(this.multiAdapter, this.writer);
	}

	@Override
	protected void prepareLiftingParticipant() {
		if (isTeam() && LiftingParticipantAdapter.isLiftingParticipantConfigured(this.loader)) {
			multiAdapter.addVisitor(new LiftingParticipantAdapter(this.writer));
		}
	}

	/**
	 * Prepares the methods callAllBindings and callOrig with an empty
	 * switch statement
	 */
	@Override
	protected void prepareForFirstTransformation() {
		if (!isTransformed && !isInterface()) {
			nodes.add(new CreateSwitchAdapter(ConstantMembers.callOrig));
			nodes.add(new CreateSwitchForCallAllBindingsNode());
			nodes.add(new CreateAddRemoveRoleMethod());
			isTransformed = true;
		}
	}

	/**
	 * Prepares the method callOrigStatic with an empty
	 * switch statement
	 */
	@Override
	protected void prepareForFirstStaticTransformation() {
		if (!isTransformedStatic && !isInterface()) {
			nodes.add(new CreateSwitchAdapter(getCallOrigStatic(), isRole()));
			isTransformedStatic = true;
		}
	}

	/**
	 * Prepares the methods access and accessStatic with an empty
	 * switch statement
	 */
	@Override
	protected void prepareForFirstMemberAccess() {
		if (!isTransformedForMemberAccess && !isInterface()) {
			nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.access,
					getInternalSuperClassName(), this));
			nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.accessStatic,
					getInternalSuperClassName(), this));
			isTransformedForMemberAccess = true;
		}

	}

	/**
	 * Was the class already transformed?
	 */
	@Override
	public boolean isFirstTransformation() {
		return isFirstTransformation;
	}
}
