public class ExportDataWeirdness {
	
	private class MyType extends SimpleType {
		//1. Test without JavaScriptObject as value for FIELD_NAME, FIELD_OTHER
		//   OK: the TreeGrid name column uses the setShortDisplayFormatter
		//2. Test with JavaScriptObject as value for FIELD_NAME, FIELD_OTHER
		//   NOK: the TreeGrid name column shows [object Object]
		
		public static final String FIELD_REF = "ref";
		public static final String FIELD_DESC = "desc";
		
		
		public MyType() {
			super("mine", FieldType.ANY);

			setShortDisplayFormatter(new SimpleTypeFormatter() {
				
				public String format(Object value, DataClass field, DataBoundComponent component, Record record) {
					if (value == null) return null;
					
					if (value instanceof JavaScriptObject) {
						JavaScriptObject jso = (JavaScriptObject)value;
						String ref = JSOHelper.getAttribute(jso, FIELD_REF);
						if (ref != null && ref.length() > 0) return "Product ref# " + String.valueOf(ref);
						String desc = JSOHelper.getAttribute(jso, FIELD_DESC);
						return desc;
					}
					// an else should never happen
					
					return "NOT A JSO: " + String.valueOf(value);
				}
			});
		}
	}
	
	private class MyButton extends Button {
		public MyButton(String key, String title) {
			super(title);
			setAttribute("exportType", key, true);
		}
	}
	
	private static final String FIELD_SELECTED = "_selectMe";
	private static final String FIELD_ID = "id";
	private static final String FIELD_NAME = "name";
	private static final String FIELD_OTHER = "anotherName";
	private static final String FIELD_PARENT = "parent";

	public Canvas getTestCase() {
		new MyType().register();
		
		HLayout layout = new HLayout();
		layout.setMembers(getGridCase(), getTreeCase());
		return layout;
	}
	
	private VLayout getGridCase() {
		
		final ListGrid grid = new ListGrid();
		ListGridField field1 = new ListGridField("a");
		ListGridField field2 = new ListGridField("b");
		ListGridField field3 = new ListGridField("lang");
		ListGridField field4 = new ListGridField("cur");
		ListGridField field5 = new ListGridField("empty");
		grid.setFields(field1, field2, field3, field4, field5);
		grid.setShowRowNumbers(true); // init now, or nullpointer later
		
		final ListGridRecord record1 = new ListGridRecord();
		record1.setAttribute("a", "this is A");
		record1.setAttribute("b", "French");
		record1.setAttribute("lang", "Être à côté de la plaçe");
		record1.setAttribute("cur", "€1.250,23");
		record1.setAttribute("empty", "");
		final ListGridRecord record2 = new ListGridRecord();
		record2.setAttribute("a", "this is \"something\"");
		record2.setAttribute("b", "Japanese");
		record2.setAttribute("lang", "ピックアップ");
		record2.setAttribute("cur", "¥50,2345.12");
		final ListGridRecord record3 = new ListGridRecord();
		record3.setAttribute("a", "oh well");
		record3.setAttribute("b", "English");
		record3.setAttribute("lang", "I am a standard language without accents");
		record3.setAttribute("cur", "$1,166.99");
		grid.setData(new ListGridRecord[] { record1, record2, record3 });
		
		Button changeRowNumbers = new Button("Set Row Numbers");
		changeRowNumbers.addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent event) {
				grid.setShowRowNumbers(!grid.getShowRowNumbers());
				
				grid.refreshFields();
			}
		});
		
		
		HLayout exportLayout = new HLayout();
		
		LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();  
        valueMap.put(ExportFormat.CSV.getValue(), "Export CSV (Excel)");  
        valueMap.put(ExportFormat.XML.getValue(), "Export XML");  
        valueMap.put(ExportFormat.XLS.getValue(), "Export XLS (Excel97)");  
        valueMap.put(ExportFormat.OOXML.getValue(), "Export XLSX (Excel2007/OOXML)");

        for (Map.Entry<String, String> e : valueMap.entrySet()) {

        	MyButton export = new MyButton(e.getKey(), e.getValue());
        	export.addClickHandler(new ClickHandler() {

        		public void onClick(ClickEvent event) {
        			String exportAs = ((Button)(event.getSource())).getAttribute("exportType");

        			DSRequest requestProperties = new DSRequest();
        			requestProperties.setExportAs((ExportFormat)EnumUtil.getEnum(ExportFormat.values(), exportAs));
        			requestProperties.setExportDisplay(ExportDisplay.DOWNLOAD);
        			requestProperties.setExportFilename("export" + new Random().nextInt(999999));
        			grid.exportClientData(requestProperties);
        		}
        	});
        	
        	exportLayout.addMember(export);
        }

		VLayout layout = new VLayout();
		layout.setMembers(grid, changeRowNumbers, exportLayout);
		return layout;
	}
	
	private VLayout getTreeCase() {
		final TreeGrid grid = new TreeGrid();
		grid.setCanSort(false);
		grid.setCanEdit(false);
		grid.setHeight(300);
		grid.setShowPartialSelection(true);
		grid.setCascadeSelection(true);
		grid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
		grid.setSelectionProperty(FIELD_SELECTED);
		grid.setShowSelectedStyle(false);
		grid.setFixedRecordHeights(false);
		grid.setWrapCells(true);
		
		
		ListGridField field1 = new ListGridField(FIELD_ID);
		ListGridField field2 = new ListGridField(FIELD_NAME);
		field2.setAttribute("type", "mine");
		ListGridField field3 = new ListGridField(FIELD_OTHER);
		field3.setAttribute("type", "mine");
		ListGridField field4 = new ListGridField(FIELD_PARENT);
		field4.setHidden(true); //causes (TypeError): _18 is null
		grid.setFields(field2, field3, field1, field4);
		
		TreeNode rootNode = new TreeNode();
		int rootNodeID = 0;
		rootNode.setAttribute(FIELD_ID, rootNodeID);
		rootNode.setAttribute(FIELD_NAME, "root");

		TreeNode [] records = new TreeNode[13];
		for (int i=0; i<records.length; i++) {
			records[i] = new TreeNode();
			records[i].setAttribute(FIELD_ID, (i+1));
			JavaScriptObject jso = JSOHelper.createObject();
			JSOHelper.setAttribute(jso, MyType.FIELD_DESC, "This is sample #" + (i+1));
			JSOHelper.setAttribute(jso, MyType.FIELD_REF, "CAT " +   (10000 + (i+1))  );
			records[i].setAttribute(FIELD_NAME, jso);
			
			jso = JSOHelper.createObject();
			JSOHelper.setAttribute(jso, MyType.FIELD_DESC, "rec " + (i+1));
			JSOHelper.setAttribute(jso, MyType.FIELD_REF, "CAT " +   (10000 + (i+1))  );
			records[i].setAttribute(FIELD_OTHER, jso);
			
			records[i].setAttribute(FIELD_SELECTED, i % 3 == 0 ? true : false);
			records[i].setAttribute(FIELD_PARENT, i/2);
		}
		
		Tree dataTree = new Tree();
		dataTree.setModelType(TreeModelType.PARENT);
		dataTree.setIdField(FIELD_ID);
		dataTree.setParentIdField(FIELD_PARENT);
		dataTree.setNameProperty(null); //no name, built in fallback is ID
		dataTree.setAutoOpenRoot(true);
		dataTree.setReportCollisions(false);
		dataTree.setShowRoot(false);
		dataTree.setAutoOpenRoot(true);
		dataTree.setRoot(rootNode);
		dataTree.setData(records);
		grid.setData(dataTree);
		
		
		
		
		HLayout exportLayout = new HLayout();
		
		LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();  
        valueMap.put(ExportFormat.CSV.getValue(), "Export CSV (Excel)");  
        valueMap.put(ExportFormat.XML.getValue(), "Export XML");  
        valueMap.put(ExportFormat.XLS.getValue(), "Export XLS (Excel97)");  
        valueMap.put(ExportFormat.OOXML.getValue(), "Export XLSX (Excel2007/OOXML)");

        for (Map.Entry<String, String> e : valueMap.entrySet()) {

        	MyButton export = new MyButton(e.getKey(), e.getValue());
        	export.addClickHandler(new ClickHandler() {

        		public void onClick(ClickEvent event) {
        			String exportAs = ((Button)(event.getSource())).getAttribute("exportType");

        			DSRequest requestProperties = new DSRequest();
        			requestProperties.setExportAs((ExportFormat)EnumUtil.getEnum(ExportFormat.values(), exportAs));
        			requestProperties.setExportDisplay(ExportDisplay.DOWNLOAD);
        			requestProperties.setExportFilename("export" + new Random().nextInt(999999));
        			grid.exportClientData(requestProperties);
        		}
        	});
        	
        	exportLayout.addMember(export);
        }
		
		VLayout layout = new VLayout();
		layout.setMembers(grid, exportLayout);
		return layout;
	}
}
