/**************************************************************
 * 
 * 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.gui;

import static org.openoffice.test.vcl.Tester.*;
import static testlib.gui.UIMap.*;

import java.lang.reflect.Array;
import java.util.StringTokenizer;
import java.util.logging.Logger;

public class SCTool {

	private static Logger LOG = Logger.getLogger(SCTool.class.getName());

	/**
	 * Select a range.
	 * 
	 * @param range
	 *            e.g. Sheet1.A10, Sheet1.A11:B30, A11, A30:B45
	 */
	public static void selectRange(String range) {
		scInputBarPosition.click(0.5, 0.5);
		scInputBarPosition.setText(range);
		typeKeys("<enter>");
		sleep(1);
	}

	/**
	 * Get the input at the given cell. If the cell is a formula, return the
	 * formula rather than the result
	 * 
	 * @param cell
	 * @return
	 */
	public static String getCellInput(String cell) {
		if (cell != null)
			selectRange(cell);
		String caption = scInputBarInput.getCaption();
		// Fix: When formulaEdit's caption is blank, the hook will return the
		// document window's caption
		// So if it's document window caption, return ""
		return caption.contains("[12479]") ? "" : caption;
	}

	/**
	 * Get the text at the given cell. If the cell is a formula, return the
	 * result rather than the formula
	 * 
	 * @param cell
	 * @return
	 */
	public static String getCellText(String cell) {
		app.setClipboard("$$$$");
		selectRange(cell);
		typeKeys("<$copy>");
		String content = app.getClipboard();
		if (content.endsWith("\r\n"))
			content = content.substring(0, content.length() - 2);
		else if (content.endsWith("\n"))
			content = content.substring(0, content.length() - 1);

		return content;
	}

	/**
	 * convert the format of column number to integer e.g. A -> 1 AA -> 27 AMJ
	 * -> 1024
	 * 
	 * @param no
	 * @return
	 */
	public static int toIntColumnNo(String no) {
		int len = no.length();
		int ret = 0;
		for (int i = 0; i < len; i++) {
			char c = no.charAt(len - i - 1);
			ret += Math.pow(26, i) * (c - 'A' + 1);
		}

		return ret;
	}

	/**
	 * Convert the format of column number to char
	 * 
	 * @param no
	 * @return
	 */
	public static String toCharColumnNo(int no) {
		String ret = "";
		int f = 0;
		do {
			f = (no - 1) / 26;
			int s = (no - 1) % 26;
			ret = (char) ('A' + s) + ret;
			no = f;
		} while (f != 0);
		return ret;
	}

	/**
	 * Parse location string into integer values
	 * 
	 * @param loc
	 *            e.g. A1
	 * @return
	 */
	public static int[] parseLocation(String loc) {
		int i = 0;
		for (; i < loc.length(); i++) {
			char c = loc.charAt(i);
			if (c >= '0' && c <= '9')
				break;
		}

		String col = loc.substring(0, i);
		String row = loc.substring(i);
		int sC = toIntColumnNo(col);
		int sR = Integer.parseInt(row);
		return new int[] { sC, sR };
	}

	/**
	 * Parse range string into integer values
	 * 
	 * @param range
	 *            e.g. A3:F9
	 * @return
	 */
	public static int[] parseRange(String range) {
		int dotIndex = range.indexOf(".");
		if (dotIndex != -1) {
			range = range.substring(dotIndex + 1);
		}

		String[] locs = range.split(":");
		int[] ret = new int[4];
		int[] start = parseLocation(locs[0]);
		ret[0] = start[0];
		ret[1] = start[1];
		if (locs.length == 1) {
			ret[2] = start[0];
			ret[3] = start[1];
		} else {
			int[] end = parseLocation(locs[1]);
			ret[2] = end[0];
			ret[3] = end[1];
		}

		return ret;
	}

	/**
	 * Get the text at the given cells. If the cell is a formula, return the
	 * result rather than the formula. Note:
	 * 
	 * @param range
	 *            e.g. A3:D9
	 * @return
	 */
	public static String[][] getCellTexts(String range) {
		selectRange(range);
		int[] intRange = parseRange(range);
		int rowCount = intRange[3] - intRange[1] + 1;
		int colCount = intRange[2] - intRange[0] + 1;
		String[][] texts = new String[rowCount][colCount];

		app.setClipboard("$$$$");
		typeKeys("<$copy>");
		sleep(1);
		String text = app.getClipboard();
		StringTokenizer tokenizer = new StringTokenizer(text, "\"\t\n", true);
		int state = 0;
		String cellContent = "";
		int r = 0, c = 0;
		while (tokenizer.hasMoreTokens()) {
			String token = tokenizer.nextToken();
			switch (state) {
			case 0:
				if ("\"".equals(token)) {
					state = 1;
				} else if ("\t".equals(token)) {
					texts[r][c] = cellContent;
					cellContent = "";
					c++;
				} else if ("\n".equals(token)) {
					if (cellContent.endsWith("\r"))
						cellContent = cellContent.substring(0, cellContent.length() - 1);
					texts[r][c] = cellContent;
					cellContent = "";
					c = 0;
					r++;
				} else {
					cellContent += token;
				}
				break;
			case 1:
				if ("\"".equals(token)) {
					state = 0;
				} else {
					cellContent += token;
				}
				break;
			}
		}

		LOG.info("Text of range [" + range + "]:\n" + arrayToString(texts));
		return texts;
	}

	private static String arrayToString(Object array) {
		if (array == null)
			return "null";
		if (!array.getClass().isArray())
			return array.toString();

		int len = Array.getLength(array);
		String ret = "{";
		for (int i = 0; i < len; i++) {
			Object el = Array.get(array, i);
			if (el == null) {
				ret += "null";
			} else if (el.getClass().isArray()) {
				ret += arrayToString(el);
			} else {
				ret += "\"" + el + "\"";
			}

			if (i + 1 != len)
				ret += ",";

		}
		ret += "}";
		return ret;
	}
}