/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/


package testlib.uno;

import java.util.Random;

import com.sun.star.beans.Property;
import com.sun.star.beans.PropertyAttribute;
import com.sun.star.beans.XPropertySet;
import com.sun.star.beans.XPropertySetInfo;
import com.sun.star.uno.UnoRuntime;

import testlib.uno.CellInfo;


/**
 * Utilities for UNO automation testing
 *
 */

public class TestUtil {
	
	private static int colLimit = 1024;
	private static int rowLimit = 1048576;
	private static Random random = new Random();

	public TestUtil() {
		
	}
	
	/**
	 * Generate a random cell index
	 * @return cellIndex    column: cellIndex[0]  row: cellIndex[1]
	 * @throws Exception
	 */
	public static CellInfo randCell() throws Exception {
		CellInfo cInfo = new CellInfo();
		
		cInfo.setCol(random.nextInt(colLimit));
		cInfo.setRow(random.nextInt(rowLimit));
		
		return cInfo;
	}
	
	/**
	 * Generate a random cell index, in the limited range
	 * @param colTop  The max column limit 
	 * @param rowTop  The max row limit
	 * @return
	 * @throws Exception
	 */
	public static CellInfo randCell(int colTop, int rowTop) throws Exception {
		CellInfo cInfo = new CellInfo();
		
		cInfo.setCol(random.nextInt(colTop));
		cInfo.setRow(random.nextInt(rowTop));
		
		return cInfo;
	}
	
	/**
	 * Generate a font size number in limited range
	 * @param max  The font size in Excel2003 is [1,409]
	 * @return
	 * @throws Exception
	 */
	public static double randFontSize(int max) throws Exception {
		double basic = random.nextInt(max * 2);
		double size = 1;
		if (basic < 2) {
			size = 1;
		}
		else {
			size = basic / 2;
		}

		return size;
	}
	
	/**
	 * Generate a series of font size number 
	 * @param listSize
	 * @param max
	 * @return
	 * @throws Exception
	 */
	public static double[] randFontSizeList(int listSize, int max) throws Exception {
		double[] sizeList = new double[listSize];
		for (int i =0; i < listSize; i++) {
			sizeList[i] = randFontSize(max);
		}
		return sizeList;
	}
	
	/**
	 * Generate a random decimal RGB color number
	 * @return
	 * @throws Exception
	 */
	public static int randColor() throws Exception {
		int r = random.nextInt(256);
		int g = random.nextInt(256);
		int b = random.nextInt(256);

		return r * 65536 + g * 256 + b; 
	}
	
	/**
	 * Generate a random decimal RGB color number in limited color space
	 * @param rMax  The R value limit, get a value in [0, rMax]
	 * @param gMax  The G value limit, get a value in [0, gMax]
	 * @param bMax  The B value limit, get a value in [0, bMax]
	 * @return
	 * @throws Exception
	 */
	public static int randColor(int rMax, int gMax, int bMax) throws Exception {
		int r = random.nextInt(rMax + 1) % 256;
		int g = random.nextInt(gMax + 1) % 256;
		int b = random.nextInt(bMax + 1) % 256;

		return r * 65536 + g * 256 + b; 
	}
	
	/**
	 * Generate a series of decimal RGB color number
	 * @param size Set the quantity of random color value generated into the array
	 * @return
	 * @throws Exception
	 */
	public static int[] randColorList(int size) throws Exception {
		int[] colorList = new int[size];
		for (int i = 0; i < size; i++) {
			colorList[i] = randColor();
		}
		
		return colorList;
	}
	
	/**
	 * Add "=" before a string
	 * @param expression
	 * @return
	 */
	public static String toFormula(String expression) {
		return "=" + expression;
	}
	
	/**
	 * Use specific operator to connect a series of number
	 * @param number
	 * @param operator
	 * @return
	 */
	public static String connectByOperator(double[] number, String operator) throws Exception{
		StringBuffer buffer = new StringBuffer();
		
		for (int i = 0; i < number.length; i++) {
			buffer.append(number[i]);
			if (i < number.length - 1) {
				buffer.append(operator);
			}
		}
		return buffer.toString();
	}
		
	/**
	 * Print the properties list of specific object to console
	 * @param obj   The instance of the object of which the property list you want to get. e.g. instance of XCell.
	 * @throws Exception
	 */
	public static void printPropertiesList(Object obj) throws Exception {
		// Get the property set of specific object
		XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, obj);
		XPropertySetInfo xPropertySetInfo = xPropertySet.getPropertySetInfo();
		 
	    // Get all properties info
	    Property[] aProps = xPropertySetInfo.getProperties();

	    for (int i = 0; i < aProps.length; i++) {
	        // Print name and type of each property
	    	System.out.print("[" + (i + 1) + "]: Name=\"" + aProps[i].Name + "\" " + aProps[i].Type.toString() + " (");
	 
	        // Get flag. pay attention to the READONLY properties
	        short nAttribs = aProps[i].Attributes;
	        if ((nAttribs & PropertyAttribute.MAYBEVOID) != 0)
	        	System.out.print("MAYBEVOID|");
	        if ((nAttribs & PropertyAttribute.BOUND) != 0)
	            System.out.print("BOUND|");
	        if ((nAttribs & PropertyAttribute.CONSTRAINED) != 0)
	            System.out.print("CONSTRAINED|");
	        if ((nAttribs & PropertyAttribute.READONLY) != 0)
	            System.out.print("READONLY|");
	        if ((nAttribs & PropertyAttribute.TRANSIENT) != 0)
	            System.out.print("TRANSIENT|");
	        if ((nAttribs & PropertyAttribute.MAYBEAMBIGUOUS ) != 0)
	            System.out.print("MAYBEAMBIGUOUS|");
	        if ((nAttribs & PropertyAttribute.MAYBEDEFAULT) != 0)
	            System.out.print("MAYBEDEFAULT|");
	        if ((nAttribs & PropertyAttribute.REMOVEABLE) != 0)
	            System.out.print("REMOVEABLE|");
	        
	        System.out.println(")");
        }

	}
	
}
