/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tests.junit;


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

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

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableTree;
import org.eclipse.swt.custom.TableTreeItem;
import org.eclipse.swt.widgets.TableColumn;
import org.junit.Before;
import org.junit.Test;

/**
 * Automated Test Suite for class org.eclipse.swt.custom.TableTree
 *
 * @see org.eclipse.swt.custom.TableTree
 */
@SuppressWarnings("deprecation")
public class Test_org_eclipse_swt_custom_TableTree extends Test_org_eclipse_swt_widgets_Composite {

@Override
@Before
public void setUp() {
	super.setUp();
	tableTree = new TableTree(shell, style = SWT.MULTI);
	setWidget(tableTree);
}

@Override
@Test
public void test_ConstructorLorg_eclipse_swt_widgets_CompositeI() {
}

@Test
public void test_getSelection() {
	int number = 8;
	TableTreeItem[] items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, SWT.NONE);
	}
	assertArrayEquals("MULTI: After adding items, but before selecting any", new TableTreeItem[] {}, tableTree.getSelection());

	// getSelection() is further tested in test_selectAll and test_setSelection$Lorg_eclipse_swt_custom_TableTreeItem
}

@Test
public void test_getSelectionCount() {
	int number = 8;
	TableTreeItem[] items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, SWT.NONE);
	}
	assertEquals("MULTI: After adding items, but before selecting any", 0, tableTree.getSelectionCount());

	// getSelectionCount() is further tested in test_selectAll and test_setSelection$Lorg_eclipse_swt_custom_TableTreeItem
}

@Override
@Test
public void test_getChildren() {
	/* Overriding test_getChildren from Test_org_eclipse_swt_widgets_Composite
	 * to do nothing, because the child of a TableTree is always a Table.
	 */
}

@Test
public void test_selectAll() {
	/* FUTURE: Should also add sub-nodes, and test both single and multi with those.
	 * i.e. subitems[i] = new TableTreeItem(items[i], SWT.NONE); */

	selectAll_helper("Empty table tree", new TableTreeItem[] {});

	int number = 8;
	TableTreeItem[] items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, SWT.NONE);
	}
	selectAll_helper("selectAll()", items);


	/* Now run the same tests on a single-select TableTree. */
	singleSelect();
	selectAll_helper("Empty table tree", new TableTreeItem[] {});

	items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, SWT.NONE);
	}
	selectAll_helper("selectAll()", new TableTreeItem[] {});
}

@Test
public void test_setSelection$Lorg_eclipse_swt_custom_TableTreeItem() {
	/* FUTURE: Should also add sub-nodes, and test both single and multi with those.
	 * i.e. subitems[i] = new TableTreeItem(items[i], SWT.NONE); */

	setSelection_helper("Select no items in empty table tree", new TableTreeItem[] {}, new TableTreeItem[] {});
	try {
		tableTree.setSelection((TableTreeItem[]) null);
		fail("MULTI: No exception thrown for selecting null in empty table tree");
	}
	catch (IllegalArgumentException e) {
	}

	int number = 8;
	TableTreeItem[] items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, 0);
	}

	setSelection_helper("Select no items in table tree with items", new TableTreeItem[] {}, new TableTreeItem[] {});
	try {
		tableTree.setSelection((TableTreeItem[]) null);
		fail("MULTI: No exception thrown for selecting null in table tree with items");
	}
	catch (IllegalArgumentException e) {
	}

	for (int i = 0; i < number; i++) {
		setSelection_helper("Select item " + i, new TableTreeItem[] {items[i]}, new TableTreeItem[] {items[i]});
	}
	setSelection_helper("Select items", items, items);
	setSelection_helper("Select tableTree.getItems()", tableTree.getItems(), tableTree.getItems());
	setSelection_helper("Select 2 contiguous items", new TableTreeItem[] {items[0], items[1]}, new TableTreeItem[] {items[0], items[1]});
	setSelection_helper("Select 2 non-contiguous items", new TableTreeItem[] {items[3], items[6]}, new TableTreeItem[] {items[3], items[6]});
	setSelection_helper("Select 3 contiguous items", new TableTreeItem[] {items[2], items[3], items[4]}, new TableTreeItem[] {items[2], items[3], items[4]});
	setSelection_helper("Select 3 non-contiguous items", new TableTreeItem[] {items[2], items[5], items[7]}, new TableTreeItem[] {items[2], items[5], items[7]});
	setSelection_helper("Select 3 unordered contiguous items", new TableTreeItem[] {items[4], items[2], items[3]}, new TableTreeItem[] {items[2], items[3], items[4]});
	setSelection_helper("Select 3 unordered non-contiguous items", new TableTreeItem[] {items[5], items[2], items[7]}, new TableTreeItem[] {items[2], items[5], items[7]});
	setSelection_helper("Select 3 reverse-order contiguous items", new TableTreeItem[] {items[4], items[3], items[2]}, new TableTreeItem[] {items[2], items[3], items[4]});
	setSelection_helper("Select 3 reverse-order non-contiguous items", new TableTreeItem[] {items[7], items[5], items[2]}, new TableTreeItem[] {items[2], items[5], items[7]});
	setSelection_helper("Select same item twice", new TableTreeItem[] {items[0], items[4], items[0]}, new TableTreeItem[] {items[0], items[4]});
	setSelection_helper("Select same item multiple times", new TableTreeItem[] {items[4], items[4], items[4], items[4], items[4], items[4]}, new TableTreeItem[] {items[4]});
	setSelection_helper("Select multiple items multiple times", new TableTreeItem[] {items[4], items[0], items[2], items[4], items[4], items[0], items[4], items[2]}, new TableTreeItem[] {items[0], items[2], items[4]});


	/* Now run the same tests on a single-select TableTree. */
	singleSelect();

	setSelection_helper("Select no items in empty table tree", new TableTreeItem[] {}, new TableTreeItem[] {});
	try {
		tableTree.setSelection((TableTreeItem[]) null);
		fail("SINGLE: No exception thrown for selecting null in empty table tree");
	}
	catch (IllegalArgumentException e) {
	}

	items = new TableTreeItem[number];
	for (int i = 0; i < number; i++) {
		items[i] = new TableTreeItem(tableTree, 0);
	}

	setSelection_helper("Select no items in table tree with items", new TableTreeItem[] {}, new TableTreeItem[] {});
	try {
		tableTree.setSelection((TableTreeItem[]) null);
		fail("SINGLE: No exception thrown for selecting null in table tree with items");
	}
	catch (IllegalArgumentException e) {
	}

	for (int i = 0; i < number; i++) {
		setSelection_helper("Select item " + i, new TableTreeItem[] {items[i]}, new TableTreeItem[] {items[i]});
	}
	setSelection_helper("Select items", items, new TableTreeItem[] {});
	setSelection_helper("Select tableTree.getItems()", tableTree.getItems(), new TableTreeItem[] {});
	setSelection_helper("Select 2 contiguous items", new TableTreeItem[] {items[0], items[1]}, new TableTreeItem[] {});
	setSelection_helper("Select 2 non-contiguous items", new TableTreeItem[] {items[3], items[6]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 contiguous items", new TableTreeItem[] {items[2], items[3], items[4]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 non-contiguous items", new TableTreeItem[] {items[2], items[5], items[7]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 unordered contiguous items", new TableTreeItem[] {items[4], items[2], items[3]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 unordered non-contiguous items", new TableTreeItem[] {items[5], items[2], items[7]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 reverse-order contiguous items", new TableTreeItem[] {items[4], items[3], items[2]}, new TableTreeItem[] {});
	setSelection_helper("Select 3 reverse-order non-contiguous items", new TableTreeItem[] {items[7], items[5], items[2]}, new TableTreeItem[] {});
	setSelection_helper("Select same item twice", new TableTreeItem[] {items[0], items[4], items[0]}, new TableTreeItem[] {});
	setSelection_helper("Select same item multiple times", new TableTreeItem[] {items[4], items[4], items[4], items[4], items[4], items[4]}, new TableTreeItem[] {});
	setSelection_helper("Select multiple items multiple times", new TableTreeItem[] {items[4], items[0], items[2], items[4], items[4], items[0], items[4], items[2]}, new TableTreeItem[] {});
}

/* custom */
private TableTree tableTree;
private int style;

/*
 * Sets a single-select TableTree as the test widget.
 * Note: This method must be private or protected so that the auto-gen tool keeps it.
 */
private void singleSelect() {
	tableTree.dispose();
	tableTree = new TableTree(shell, style = SWT.SINGLE);
	setWidget(tableTree);
}

/*
 * Used in test_selectAll.
 * Note: This method must be private or protected so that the auto-gen tool keeps it.
 */
private void selectAll_helper(String message, TableTreeItem[] expectedSelection) {
	tableTree.selectAll();
	message = (style == SWT.MULTI ? "MULTI" : "SINGLE") + ": " + message;
	assertEquals(message, expectedSelection.length, tableTree.getSelectionCount());
	assertArrayEquals(message, expectedSelection, tableTree.getSelection());
}

/*
 * Used in test_setSelection$Lorg_eclipse_swt_custom_TableTreeItem.
 * Note: This method must be private or protected so that the auto-gen tool keeps it.
 */
private void setSelection_helper(String message, TableTreeItem[] itemsToSelect, TableTreeItem[] expectedSelection) {
	tableTree.setSelection(itemsToSelect);
	message = (style == SWT.MULTI ? "MULTI" : "SINGLE") + ": " + message;
	assertEquals(message, expectedSelection.length, tableTree.getSelectionCount());
	assertArrayEquals(message, expectedSelection, tableTree.getSelection());
}

private void createTableTree(List<String> events, boolean traverse) {
    String test = getTestName();
    tableTree = new TableTree(shell, SWT.BORDER | SWT.SINGLE);
	for (int col = 0; col < 3; col++) {
		TableColumn column = new TableColumn(tableTree.getTable(), SWT.NONE);
		column.setText("Col " + col);
		column.setWidth(70);
		hookExpectedEvents(column, test, events);
	}
	for (int node = 0; node < 4; node++) {
		TableTreeItem item = new TableTreeItem(tableTree, SWT.NONE);
		for (int col = 0; col < 3; col++) {
			item.setText(col, "TTItem" + node + col);
		}
		hookExpectedEvents(item, test, events);
		TableTreeItem subitem = new TableTreeItem(item, SWT.NONE);
		for (int col = 0; col < 3; col++) {
			subitem.setText(col, "TTSub" + node + col);
		}
		hookExpectedEvents(subitem, test, events);
	}
	String[] types = ConsistencyUtility.eventOrdering.get("TableTreeTable");
	if(!traverse) {
	    String[] temp = new String[types.length -1];
	    System.arraycopy(types, 0, temp, 0, types.length-1);
	    types = temp;
	}
	hookExpectedEvents(tableTree.getTable(), types, events);
	setWidget(tableTree);
}

@Test
public void test_consistency_KeySelection() {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(0, SWT.ARROW_DOWN, 0, 0, ConsistencyUtility.KEY_PRESS, events);
}

@Test
public void test_consistency_MouseSelection() {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(30, 30, 1, 0, ConsistencyUtility.MOUSE_CLICK, events);
}

@Test
public void test_consistency_MouseExpand() {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(11, 10, 1, 0, ConsistencyUtility.MOUSE_CLICK, events);
}

@Test
public void test_consistency_KeyExpand() {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    tableTree.setSelection(new TableTreeItem[] { tableTree.getItems()[0]});
    int code=SWT.ARROW_RIGHT;
    if(SwtTestUtil.isGTK)
        code = SWT.KEYPAD_ADD;
    consistencyEvent(0, code, 0, 0, ConsistencyUtility.KEY_PRESS, events);
}

@Test
public void test_consistency_DoubleClick () {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyPrePackShell();
    consistencyEvent(20, tableTree.getItemHeight()*2, 1, 0,
            	     ConsistencyUtility.MOUSE_DOUBLECLICK, events);
}

@Test
public void test_consistency_EnterSelection () {
    List<String> events = new ArrayList<>();
    createTableTree(events, false);
    consistencyEvent(13, 10, 0, 0, ConsistencyUtility.KEY_PRESS, events);
}

@Test
public void test_consistency_SpaceSelection () {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(' ', 32, 0, 0, ConsistencyUtility.KEY_PRESS, events);
}

@Test
public void test_consistency_MenuDetect () {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(50, 25, 3, 0, ConsistencyUtility.MOUSE_CLICK, events);
}

@Test
public void test_consistency_DragDetect () {
    List<String> events = new ArrayList<>();
    createTableTree(events, true);
    consistencyEvent(30, 20, 50, 30, ConsistencyUtility.MOUSE_DRAG, events);
}

}
