package org.apache.ode.bpel.obj.migrate;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.obj.ExtensibleImpl;

/**
 * Migrate from old Omodel classes to new ones.
 * @author fangzhen
 * @see ObjectTraverser
 */
public class OmOld2new extends AbstractObjectVisitor{
    private static final Logger __log = LoggerFactory.getLogger(OmOld2new.class);
    
	private static Map<String, String> beanPkgMap = new HashMap<String, String>();
	static{
		beanPkgMap.put("org.apache.ode.bpel.o", "org.apache.ode.bpel.obj");
		beanPkgMap.put("org.apache.ode.bpel.elang.xpath10.o", "org.apache.ode.bpel.elang.xpath10.obj");
		beanPkgMap.put("org.apache.ode.bpel.elang.xpath20.o", "org.apache.ode.bpel.elang.xpath20.obj");
		beanPkgMap.put("org.apache.ode.bpel.elang.xquery10.o", "org.apache.ode.bpel.elang.xquery10.obj");
	}
	
	public Object visit(Object obj){
		__log.debug("migrating object: " + obj.getClass() + "@" + System.identityHashCode(obj));
		Object n;
		/*
		 * we use two category of visitXXX methods here. The first  visitXXX(Object) 
		 * return corresponding new object instance without fulfilling its contents, 
		 * which avoids recursively call. And then assign the new object. then fill contents.
		 * other wise, on cyclic reference case, the object re-visited but hasn't prepared yet.
		 * However, this workaround assumes that the new object is mutable, which is true in our case.
		 */
		if (isMap(obj)){
			n = visitMap(obj);
		}else if (isCollection(obj)){
			n = visitCollection(obj);
		}else if (isArray(obj)){
			n = visitArray(obj);
		}else{
			n = visitPojo(obj);
		}
		rtab.assign(obj, n);
		
		if (isMap(obj)){
			visitMap(obj, n);
		}else if (isCollection(obj)){
			visitCollection(obj, n);
		}else if (isArray(obj)){
			visitArray(obj, n);
		}else{
			visitPojo(obj, n);
		}
		return n;
	}


	@Override
	protected boolean isCollection(Object old) {
		return (old instanceof Collection);
	}

	private boolean isOmodelBean(Object old){
		Class<?> cls = old.getClass();
		if (beanPkgMap.containsKey(cls.getPackage().getName()) &&
				!cls.getSimpleName().equals("Serializer")){
			return true;
		}
		return false;
	}
	@Override
	public Object visitArray(Object old) {
		throw new UnsupportedOperationException("Create new Array is unsupported");
	}

	private void visitArray(Object obj, Object n) {
		throw new UnsupportedOperationException("We don't need the method here");
	}

	@Override
	@SuppressWarnings({ "rawtypes"})
	public Object visitCollection(Object old) {
		Collection o = (Collection) old;
		try {
			Collection n = o.getClass().newInstance();
			return n;
		} catch (Exception e){
			//should not get here
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void visitCollection(Object old, Object nu) {
		Collection o = (Collection) old;
		Collection n = (Collection) nu;
		for (Object obj : o){
			n.add(traverse.traverseObject(obj));
		}
	}

	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Object visitMap(Object old) {
		Map o = (Map) old;
		try{
			Map n = o.getClass().newInstance();
			return n;
		}catch (Exception e){
			//should not get here
			e.printStackTrace();			
		}
		return null;
	}
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void visitMap(Object obj, Object nu) {
		Set<Entry> entries = ((Map)obj).entrySet();
		Map n = (Map)nu;
		for (Entry e : entries){
			n.put(traverse.traverseObject(e.getKey()), traverse.traverseObject(e.getValue()));
		}
	}

	@Override
	public Object visitPojo(Object old) {
		if (!isOmodelBean(old)){
			return old;
		}else{
			return initiateNew(old);
		}
	}

	private void visitPojo(Object old, Object n) {
		if (isOmodelBean(old)){
			constructNewOm(old, n);
		}
	}
	/**
	 * construct new omodel instances from old ones. Assume <code>old</code> is an old OmodelBean
	 * @param old
	 * @return
	 */
	private Object constructNewOm(Object old, Object tn) {
		assert tn instanceof ExtensibleImpl;
		ExtensibleImpl n = (ExtensibleImpl) tn;
		List<Field> fields  = getAllFields(old.getClass());
		Map<String, Object> fieldMap = n.getFieldContainer();
		for (Field f : fields){
			if ((f.getModifiers() & Modifier.STATIC) != 0){
				continue; //skip static fields
			}
			f.setAccessible(true);
			try{
				String fname = f.getName();
				Object fvalue = f.get(old);
				if (fvalue != null){
					fieldMap.put(fname, traverse.traverseObject(fvalue));
				}else{
					fieldMap.put(fname, null);
				}
			} catch (Exception e) {
				RuntimeException rte = new RuntimeException(
						"Error when try to construct corresponding new Omodel class from old one:"
						+old.getClass() + "; Failed on field:" + f.getName());
				rte.initCause(e);
				throw rte;
			}
		}
		n.setClassVersion(1);
		n.setOriginalVersion(0);
		return n;
	}
	
	private List<Field> getAllFields(Class cls) {
		return getAllFieldsRec(cls, new ArrayList<Field>());
	}

	private List<Field> getAllFieldsRec(Class cls, ArrayList<Field> fields) {
		Class par = cls.getSuperclass();
		if (par != null){
			getAllFieldsRec(par, fields);
		}
		fields.addAll(Arrays.asList(cls.getDeclaredFields()));
		return fields;
	}

	private Object initiateNew(Object old) {
		String clsName = old.getClass().getName();
		String qcls = clsName.replace(".o.", ".obj.");
		try {
			Constructor cons = Class.forName(qcls).getConstructor();
			cons.setAccessible(true);
			return cons.newInstance();
		} catch (Exception e) {
			RuntimeException rte = new RuntimeException(
					"Error when try to initiate corresponding new Omodel class of old one:"
							+ old.getClass());
			rte.initCause(e);
			throw rte;
		}
	}

	@Override
	public Object visitSet(Object obj) {
		throw new UnsupportedOperationException("We don't really need this operatiion here");
	}
}
