/*******************************************************************************
 * Copyright (c) 2005, 2007 IBM Corporation 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.archive.testutilities;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.jem.java.internal.impl.JavaClassImpl;
import org.eclipse.jst.j2ee.common.CommonPackage;
import org.eclipse.jst.j2ee.ejb.EjbPackage;
import org.eclipse.jst.j2ee.webapplication.WebapplicationPackage;

public class EMFAttributeFeatureGenerator {
	public static String avClass[];
	protected static int count = 0;
	protected static Random randomGenerator = new Random();
	protected static int maxNumberOfProjectsCreated = 1000;
	protected static Map enumMap = new HashMap();
	protected static int paramCount;
	protected static String[] langArray = new String[] { "EN","FR","DE","JP","CN","BR","SP"};
	protected static int langCount = 0;  
	protected static Map booleanMap = new HashMap();
	protected static Map attIndex = new HashMap();
	protected static boolean specialNumberGen = false;
	protected static String httpArray[] = null;
	protected static int httpArrayIndex = 0;
	
	public static int version;
	public static int moduleType;
	//static versions
	public static final int VERSION_1_2 = 0;
	public static final int VERSION_1_3 = 1;
	public static final int VERSION_1_4 = 2;

	public static final int APPICATION = 0;
	public static final int APP_CLIENT = 1;
	public static final int CONNECTOR = 2;
	public static final int EJB = 3;
	public static final int WEB = 4;
	
    public EMFAttributeFeatureGenerator() {
        super();
    }
    
    public static void resetCount() {
    	count = 0;
    	return;
    }
	public static Object createAttribute(EAttribute att, EObject obj){
		return createAttribute(new EAttributeDescriptor(att,obj.eClass()));
	}
	
	public static Object createAttribute(EAttribute att, EClass eClass){
		return createAttribute(new EAttributeDescriptor(att,eClass));
	}
	
	public static Object createAttribute(EAttribute att, EObject obj, boolean special){
		specialNumberGen = special;
		return createAttribute(new EAttributeDescriptor(att,obj.eClass()));
	}
			
	public static Object createAttribute(EAttribute att, EObject obj,  boolean special, int ver, int modType) {
	   specialNumberGen = special;
	   version = ver;
	   moduleType = modType;
	   return createAttribute(new EAttributeDescriptor(att,obj.eClass()));
   }

    protected static Object createAttribute(EAttributeDescriptor att) {
		EClassifier meta = att.getFeature().getEType();
		if (meta instanceof EEnum && att.getFeature().isMany()){
			List collection = new ArrayList();
			collection.add(createEnum(att));
			return collection;
		}
		else if (meta instanceof EEnum)
			return createEnum(att);
		else if ((version == VERSION_1_3 || version == VERSION_1_2) && att.getFeature().equals(WebapplicationPackage.eINSTANCE.getHTTPMethodType_HttpMethod()))
			return createSpecialHttpMethodsFor13();
		else if (version == VERSION_1_3 && att.getFeature().equals(CommonPackage.eINSTANCE.getEJBLocalRef_Local()))
			return generateRandomAttributeString(new EAttributeDescriptor(CommonPackage.eINSTANCE.getEjbRef_Remote(), att.getMetaClass()));
		else if (version == VERSION_1_3 && att.getFeature().equals(CommonPackage.eINSTANCE.getEJBLocalRef_LocalHome()))
			return generateRandomAttributeString(new EAttributeDescriptor(CommonPackage.eINSTANCE.getEjbRef_Home(),att.getMetaClass()));
		else if (att.getFeature().getName().equals("parms"))
			return createParams(att);
		else if (att.getFeature().getName().startsWith("location") && version == VERSION_1_4)
			return createLocation(att);
		else if (att.getFeature().getName().startsWith("locale") && version == VERSION_1_4)
			return createLocale();
		else if (att.getFeature().getName().equals("lang"))
			return createLang(att);
		else if (att.getFeature().getName().equals("version"))
			if (att.getFeature() == EjbPackage.eINSTANCE.getContainerManagedEntity_Version()) 
				return "2.x";
			else
				return createVersion(att);
		else if (att.getFeature().getName().equals("mimeType") && version == VERSION_1_4)
			return "text/plain";
		else if (att.getFeature().getName().equals("errorCode") && version == VERSION_1_4)
			return "404";
		else if (att.getFeature().getName().equals("formLoginPage") && version == VERSION_1_4)
			return "/testFormLoginPage";
		else if (att.getFeature().getName().equals("formErrorPage") && version == VERSION_1_4)
			return "/testFormErrorpage";
		else if(att.getFeature().getName().equals("link") && version == VERSION_1_4)
			return "roleName_0";
		else if(att.getFeature().getName().equals("specVersion") && version == VERSION_1_4)
			return "1.5";
		else if (att.getFeature().isMany())
			return createCollection(att);
		else if (meta.getInstanceClassName().equals("java.lang.String"))
			return  generateRandomAttributeString(att);
		else if (meta.getInstanceClassName().equals("java.math.BigInteger"))
			return  generateRandomBigInteger(att);
		else if (meta.getInstanceClassName().equals("boolean"))
			return  generateRandomBoolean(att);
		else if (meta.getInstanceClassName().equals("java.util.List"))
			return  createCollection(att);
		else if(meta.getName().equals("QName")){
			return generateRandomQName(att);
		}
		switch (meta.getClassifierID()) {
			case EcorePackage.ESTRING:
				return generateRandomAttributeString(att);
			case EcorePackage.EBOOLEAN_OBJECT:
			case EcorePackage.EBOOLEAN:
				return generateRandomBoolean(att);
			case EcorePackage.EINTEGER_OBJECT:
			case EcorePackage.EINT:
				return generateRandomInteger(att);
			case EcorePackage.EBIG_INTEGER:
				return generateRandomBigInteger(att);
			case EcorePackage.EFLOAT_OBJECT:
			case EcorePackage.EFLOAT:
				return generateRandomFloat(att);
			case EcorePackage.ECHARACTER_OBJECT:
			case EcorePackage.ECHAR:
				return generateRandomChar(att);
			case EcorePackage.ELONG_OBJECT:
			case EcorePackage.ELONG:
			case XMLTypePackage.LONG:
				return generateRandomLong();
			case EcorePackage.EBYTE_OBJECT:
			case EcorePackage.EBYTE:
				return generateRandomByte();
			case EcorePackage.EDOUBLE_OBJECT:
			case EcorePackage.EDOUBLE:
				return generateRandomDouble();
			case EcorePackage.ESHORT_OBJECT:
			case EcorePackage.ESHORT:
				return generateRandomShort(att);
			case EcorePackage.EJAVA_OBJECT:
				return generateRandomObject(att);
			}
		return null;
    }

	/**
     * @return
     */
    private static Object createLocale() {
        return "en_US";
    }

    /**
     * @param att
     * @return
     */
    private static Object createLocation(EAttributeDescriptor att) {
        String temp = generateRandomAttributeString(att);
        return "/." + temp;
    }

    public static EObject createJavaClassProxy(EStructuralFeature ref, EObject eObject) {
		if (avClass == null) {
			avClass = new String[] { "java.util.HashTable", "java.util.List", "java.sql.Data", "java.lang.Integer", "java.lang.String" };
		}
		EAttributeDescriptor feature = new EAttributeDescriptor(ref,eObject.eClass());
		if (!attIndex.containsKey(feature))
			attIndex.put(feature, new Integer(0));
		int classIndex = ((Integer)attIndex.get(feature)).intValue();
		String name = avClass[classIndex];
		classIndex++;
		if (classIndex == 5)
			classIndex = 0;
		attIndex.put(feature,new Integer(classIndex));
		return JavaClassImpl.createClassRef(name);
	}
	/**
	 * @return
	 */
	protected static Object createSpecialHttpMethodsFor13() {
		if (httpArray == null)
			httpArray = new String[] {
				"GET",
				"POST",
				"PUT",
				"DELETE",
				"HEAD",
				"OPTIONS",
				"TRACE"
			};
		if (httpArrayIndex >= httpArray.length)
			httpArrayIndex = 0;
		Object holder = httpArray[httpArrayIndex]; 	
		httpArrayIndex++;
		return holder;
	}

	/**
     * @param att
     * @return
     */
    protected static String createVersion(EAttributeDescriptor att) {
		String versionHolder = "";
		switch (moduleType) {
		case APPICATION :
			if(version == VERSION_1_2) {
				versionHolder = "1.2";
				break;
			}
			else if(version == VERSION_1_3){
				versionHolder = "1.3";
				break;
			}
			else if(version == VERSION_1_4){
				versionHolder = "1.4";
				break;
			}
			else {
				versionHolder = "5.0";
				break;
			}
		case APP_CLIENT :
			if(version == VERSION_1_2) {
				versionHolder = "1.2";
				break;
			}
			else if(version == VERSION_1_3) {
				versionHolder = "1.3";
				break;
			}
			else if(version == VERSION_1_4) {
				versionHolder = "1.4";
				break;
			}
			else {
				versionHolder = "5.0";
				break;
			}
		case EJB :
			if(version == VERSION_1_2) {
				versionHolder = "1.1";
				break;
			}
			else if(version == VERSION_1_3) {
				versionHolder = "2.0";
				break;
			}
			else if(version == VERSION_1_4) {
				versionHolder = "2.1";
				break;
			}
			else {
				versionHolder = "3.0";
				break;
			}
		case CONNECTOR :
			if(version == VERSION_1_2) {
				versionHolder = "1.0";
				break;
			}
			else if(version == VERSION_1_3) {
				versionHolder = "1.0";
				break;
			}
			else { 
				versionHolder = "1.5";
				break;
			}
		case WEB :
			if(version == VERSION_1_2) {
				versionHolder = "2.2";
				break;
			}
			else if(version == VERSION_1_3) {
				versionHolder = "2.3";
				break;
			}
			else if(version == VERSION_1_4) {
				versionHolder = "2.4";
				break;
			}
			else { 
				versionHolder = "2.5";
				break;
			}
		}
		
		return versionHolder;
    }

    protected static Object createParams(EAttributeDescriptor att) {
		if (paramCount == 0){
			paramCount++;
			return null;
		}
		else if (paramCount == 1){
			paramCount++;
			return "";
		}
		String r = "";
		for (int i = 1 ; i < paramCount ;i++){
			r += generateRandomAttributeString(att) + " ";
		}
		paramCount++;
		if (paramCount == 5)
			paramCount = 0;
		return r;
		
	}


	protected static Object createLang(EAttributeDescriptor att) {
		String name = langArray[langCount];
		langCount++;
		if (langCount == 7)
			langCount = 0;
		return name;
	}

	protected static Object createCollection(EAttributeDescriptor att) {
		ArrayList list = new ArrayList();
		list.add(generateRandomAttributeString(att));
		return list;
	}


	protected static Object generateRandomObject(EAttributeDescriptor att) {
	    return generateRandomAttributeString(att);
	}

	protected static Object createEnum(EAttributeDescriptor att) {
		EEnum anEnum = (EEnum) att.getFeature().getEType();
		if (!enumMap.containsKey(att)){
			if (att.getFeature().getName().equals("authMethod"))
				enumMap.put(att,new Integer(1));
			else 
				enumMap.put(att,new Integer(0));
		}
		int pos = ((Integer)enumMap.get(att)).intValue();
		EList literals = anEnum.getELiterals();
		int size = literals.size();
		if (pos == size)
			pos = 0;
		Object holder = anEnum.getEEnumLiteral(pos).getInstance();
		pos++;
		enumMap.put(att,new Integer(pos));
		return holder;
	    
	}
	public static Object generateRandomClassname(EAttributeDescriptor att) {
		return "com.foo." + generateRandomAttributeString(att);
	}

	//REVISIT
    protected static Object generateRandomShort(EAttributeDescriptor att) {
        return new Short(Short.parseShort(String.valueOf(generateNumber(att))));
    }

    protected static Object generateRandomDouble() {
        return new Double(randomGenerator.nextDouble());
    }
	//REVISIT
    protected static Object generateRandomByte() {
        return new Byte("byte");
    }

    protected static Object generateRandomLong() {
        return new Long(randomGenerator.nextLong());
    }

    protected static Object generateRandomChar(EAttributeDescriptor att) {
        return new Character(generateRandomAttributeString(att).charAt(0));
    }


    protected static Object generateRandomFloat(EAttributeDescriptor att) {
        return new Float(randomGenerator.nextFloat());
    }

    protected static Object generateRandomInteger(EAttributeDescriptor att) {
    	return new Integer(generateNumber(att));
    }
    
    protected static Object generateRandomBigInteger(EAttributeDescriptor att) {
    	return new BigInteger(new Long(generateNumber(att)).toString());
    }
    
    protected static char [] intToCharMapping = new char [] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
    protected static char [] charToIntMapping = new char [] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    protected static Object generateRandomQName(EAttributeDescriptor att) {
    	char [] charArray = Integer.toString(generateNumber(att)).toCharArray();
    	for(int i=0;i<charArray.length;i++){
    		for(int j=0;j<charToIntMapping.length; j++){
    			if (charArray[i] == charToIntMapping[j]){
    				charArray[i] = intToCharMapping[j];
    				break;
    			}
    		}
    	}
    	return new String(charArray);
    }
    
    protected static Object generateRandomBoolean(EAttributeDescriptor att) {
		if (!booleanMap.containsKey(att)){
			booleanMap.put(att,new Boolean(true));
		}
		Boolean holder = (Boolean)booleanMap.get(att);
		booleanMap.put(att, new Boolean(!holder.booleanValue()));
		return holder;
    }

    public static String generateRandomAttributeString(EAttributeDescriptor att) {
		return att.getFeature().getName() + "_" + generateNumber(att);
	}
	protected static int generateNumber(EAttributeDescriptor att) {
		if(!specialNumberGen)
			return count ++;
		else{
			if(!attIndex.containsKey(att))
				attIndex.put(att, new Integer(0));
			int holder = ((Integer) attIndex.get(att)).intValue();
			attIndex.put(att, new Integer(holder+1));
			return holder;
		}
	}

	public static void reset(){
		count = 0;
		enumMap = new HashMap();
		httpArrayIndex = 0;
		paramCount = 0;
		langCount = 0;  
		booleanMap = new HashMap();
		attIndex = new HashMap();
		specialNumberGen = false;
		TestUtilities.reset();
		J2EEVersionCheck.cur_Tags = null;

	}
}
