/*
 * © 2013-2019 by Zappware. 
 * All Rights Reserved. No part of this application or any of its contents may be reproduced, 
 * copied, modified or adapted, without the prior written consent of Zappware.
 *
 * Website: http://www.zappware.com
 * E-Mail: info@zappware.com
 */
package com.zappware.graphlperftest.model;

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

import org.apache.commons.lang3.RandomStringUtils;

/**
 * Generator of model content.
 */
public class ModelGenerator
{
	/** An instance of TypeOne with sub objects. */
	private TypeOne typeOne;
	/** An instance of TypeTwo with sub objects. */
	private TypeTwo typeTwo;
	/** An instance of TypeThree. */
	private TypeThree typeThree;
	
	/**
	 * Constructor
	 */
	public ModelGenerator()
	{
		generateModel();
	}
	
	/**
	 * Retrieve a TypeOne instance.
	 * @return
	 */
	public TypeOne getTypeOne()
	{
		return typeOne;
	}

	/**
	 * Retrieve a TypeTwo instance.
	 * @return
	 */
	public TypeTwo getTypeTwo()
	{
		return typeTwo;
	}

	/**
	 * Retrieve a TypeThree instance.
	 * @return
	 */
	public TypeThree getTypeThree()
	{
		return typeThree;
	}
	
	/**
	 * Generate model content.
	 */
	private void generateModel()
	{
		List<TypeTwo> typeTwoChildren;
		List<TypeThree> typeThreeChildren;

		// The TypeOne instance with 25 children as propertySix, 7 children as propertySeven, 5 children as propertyEight and 10 children as propertyNine
		typeOne = generateTypeOne();

		typeTwoChildren = new ArrayList<>();
		for (int i = 0; i < 25; i++)
		{
			TypeTwo typeTwoChild = generateTypeTwo();
			typeThreeChildren = new ArrayList<>();
			for (int j = 0; j < 2; j++)
				typeThreeChildren.add(generateTypeThree());
			typeTwoChild.setPropertySix(typeThreeChildren);
			typeThreeChildren = new ArrayList<>();
			for (int j = 0; j < 4; j++)
				typeThreeChildren.add(generateTypeThree());
			typeTwoChild.setPropertySeven(typeThreeChildren);
			typeTwoChildren.add(typeTwoChild);
		}
		typeOne.setPropertySix(typeTwoChildren);

		typeTwoChildren = new ArrayList<>();
		for (int i = 0; i < 7; i++)
		{
			TypeTwo typeTwoChild = generateTypeTwo();
			typeThreeChildren = new ArrayList<>();
			for (int j = 0; j < 3; j++)
				typeThreeChildren.add(generateTypeThree());
			typeTwoChild.setPropertySix(typeThreeChildren);
			typeThreeChildren = new ArrayList<>();
			for (int j = 0; j < 2; j++)
				typeThreeChildren.add(generateTypeThree());
			typeTwoChild.setPropertySeven(typeThreeChildren);
			typeTwoChildren.add(typeTwoChild);
		}
		typeOne.setPropertySeven(typeTwoChildren);

		typeThreeChildren = new ArrayList<>();
		for (int i = 0; i < 5; i++)
			typeThreeChildren.add(generateTypeThree());
		typeOne.setPropertyEight(typeThreeChildren);
		typeThreeChildren = new ArrayList<>();
		for (int i = 0; i < 10; i++)
			typeThreeChildren.add(generateTypeThree());
		typeOne.setPropertyNine(typeThreeChildren);

		// The TypeTwo instance with 30 children as propertySix and 5 children as propertySeven.
		typeTwo = generateTypeTwo();
		typeThreeChildren = new ArrayList<>();
		for (int i = 0; i < 30; i++)
			typeThreeChildren.add(generateTypeThree());
		typeTwo.setPropertySix(typeThreeChildren);
		typeThreeChildren = new ArrayList<>();
		for (int i = 0; i < 5; i++)
			typeThreeChildren.add(generateTypeThree());
		typeTwo.setPropertySeven(typeThreeChildren);
		
		// The TypeThree instance.
		typeThree = generateTypeThree();
	}
	
	/**
	 * Generate a TypeOne instance.
	 * @return
	 */
	private TypeOne generateTypeOne()
	{
		TypeOne typeOne = new TypeOne();
		typeOne.setId(UUID.randomUUID().toString());
		typeOne.setPropertyOne(generateString());
		typeOne.setPropertyTwo(generateInt());
		typeOne.setPropertyThree(generateString());
		typeOne.setPropertyFour(generateString());
		typeOne.setPropertyFive(generateString());
		
		return typeOne;
	}

	/**
	 * Generate a TypeTwo instance.
	 * @return
	 */
	private TypeTwo generateTypeTwo()
	{
		TypeTwo typeTwo = new TypeTwo();
		typeTwo.setId(UUID.randomUUID().toString());
		typeTwo.setPropertyOne(generateInt());
		typeTwo.setPropertyTwo(generateString());
		typeTwo.setPropertyThree(generateString());
		typeTwo.setPropertyFour(generateInt());
		typeTwo.setPropertyFive(generateString());
		
		return typeTwo;
	}

	/**
	 * Generate a TypeThree instance.
	 * @return
	 */
	private TypeThree generateTypeThree()
	{
		TypeThree typeThree = new TypeThree();
		typeThree.setId(UUID.randomUUID().toString());
		typeThree.setPropertyOne(generateInt());
		typeThree.setPropertyTwo(generateString());
		typeThree.setPropertyThree(generateInt());
		typeThree.setPropertyFour(generateString());
		typeThree.setPropertyFive(generateString());
		
		return typeThree;
	}
	
	/**
	 * Generate a random alphanumeric string.
	 * @return
	 */
	private String generateString()
	{
		return RandomStringUtils.randomAlphanumeric(25);
	}
	
	/**
	 * Generate a random int.
	 * @return
	 */
	private int generateInt()
	{
		return (int) (Math.random() * 2048);
	}
}