package com.hp.isomorphic.client.issues;

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

import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.smartgwt.client.data.AdvancedCriteria;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Hilite;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.RecordList;
import com.smartgwt.client.types.GroupStartOpen;
import com.smartgwt.client.types.OperatorId;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.SelectionUpdatedEvent;
import com.smartgwt.client.widgets.grid.events.SelectionUpdatedHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class RecordUpdatesViaUpdateCaches extends VLayout{
	private ListGrid grid;
	private Hilite[] hilites = null; 
	private boolean customHiliting = false;
	private Timer timer = null;
	
	public RecordUpdatesViaUpdateCaches() {
		AdvancedCriteria hiliteCriteria = new AdvancedCriteria("contentField", OperatorId.CONTAINS, "0");
		Hilite hilite = new Hilite();
		hilite.setBackgroundColor("red");
		hilite.setTextColor("blue");
		hilite.setFieldNames("contentField", "statusField");
		hilite.setCriteria(hiliteCriteria);
		hilites = new Hilite[] {hilite};
		
		grid = new ListGrid() {
            @Override
			protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
            	if (customHiliting && hilites != null) {
					String fieldName = grid.getFieldName(colNum);
            		DataSource dataSource = getDataSource();
            		String cssText = null;
            		for (Hilite hilite: hilites) {
            			String hiliteFieldName = hilite.getFieldName();
						if (hiliteFieldName == null || fieldNamesContain(hiliteFieldName, fieldName)) {
		            		Record[] applyFilter = dataSource.applyFilter(new Record[] { record }, hilite.getCriteria());
		            		if (applyFilter.length != 0) {
		            			cssText = getHiliteCssText(hilite);
		            		}
            			}
            		}
            		
            		if (cssText != null) {
            			return cssText;
            		}
            	}
            	
                return super.getCellCSSText(record, rowNum, colNum);
            }

			private String getHiliteCssText(Hilite hilite) {
				String cssText;
				
				if (hilite.getCssText() != null) {
					cssText = hilite.getCssText() + ";";
				}
				else {
					cssText = "";
					if (hilite.getBackgroundColor() != null) {
						cssText += "background-color:" + hilite.getBackgroundColor() + ";";
					}
					
					if (hilite.getTextColor() != null) {
						cssText += "color:" + hilite.getTextColor() + ";";
					}
				}
				
				return cssText.isEmpty() ? null : cssText;
			}

			private boolean fieldNamesContain(String hiliteFieldNames, String fieldName) {
				String[] fieldNames = hiliteFieldNames.split(",");
				for (String hiliteFieldName : fieldNames) {
					if (hiliteFieldName.equals(fieldName)) {
						return true;
					}
				}
				return false;
			}
		};
		
		ListGridField gridIdField = new ListGridField("idField", "ID", 40);
		ListGridField gridStatusField = new ListGridField("statusField", "Status", 80);
		ListGridField contentField = new ListGridField("contentField", "Content", 300);
		ListGridField sortField = new ListGridField("sortField", "Sort", 100);
		ListGridField dateField = new ListGridField("dateField", "Date", 125);
		
		gridIdField.setCanDragResize(false);
		gridIdField.setCanReorder(false);

		List<ListGridField> fields = new ArrayList<>();
		fields.add(gridIdField);
		fields.add(gridStatusField);
		fields.add(contentField);
		fields.add(sortField);
		fields.add(dateField);
		
		for (int i = 0; i < 100; ++i) {
			fields.add(new ListGridField("column" + i, "Column " + i, 70));
		}
		
		RecordList recordList = GridData.createRecordList(12000);
		final ClientDataSource ds = new ClientDataSource(recordList);
		
		grid.setDataSource(ds);
		grid.setFields(fields.toArray(new ListGridField[fields.size()]));
		grid.setShowAllRecords(false);
		grid.setSelectionType(SelectionStyle.MULTIPLE);
		grid.setGroupByMaxRecords(20000);
		grid.setGroupStartOpen(GroupStartOpen.NONE);
		grid.setShowAsynchGroupingPrompt(false);
		grid.setSortField("sortField");
		grid.setShowAllColumns(false);
		grid.setAutoFetchData(true);
        
		AdvancedCriteria criteria = new AdvancedCriteria("contentField", OperatorId.NOT_CONTAINS, " - update");
		grid.setCriteria(criteria);

		grid.addSelectionUpdatedHandler(new SelectionUpdatedHandler() {
			@Override
			public void onSelectionUpdated(SelectionUpdatedEvent event) {
				GWT.log("Grid selection changed: " + grid.getSelectedRecords().length);
			}
		});
		
		addMember(grid);
		
		HLayout buttonBar = new HLayout();
		buttonBar.setAutoHeight();
		buttonBar.setWidth100();
		
		Button button = new Button("Add 1");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				ds.addData(GridData.createRecordList(1).duplicate());
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		button = new Button("Add 50");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				ds.addData(GridData.createRecordList(50).duplicate());
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		button = new Button("Remove selected");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				ds.removeData(grid.getSelectedRecords());
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		button = new Button("Update contents");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				Record [] records = grid.getSelectedRecords();
				for (Record record : records) {
					record.setAttribute("contentField", record.getAttributeAsString("contentField") + " - update");
				}
				
				ds.updateData(records);
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		button = new Button("Update sort");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				Record [] records = grid.getSelectedRecords();
				for (Record record : records) {
					record.setAttribute("sortField", GridData.getSortValue());
				}
				
				ds.updateData(records);
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		button = new Button("Update status");
		button.setWidth("*");
		button.setHeight(40);
		button.setWrap(true);
		button.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Date start = new Date();
				Record [] records = grid.getSelectedRecords();
				for (Record record : records) {
					record.setAttribute("statusField",  GridData.getStatusValue());
				}
				
				ds.updateData(records);
				showTime(start);
			}
		});
		
		buttonBar.addMember(button);
		
		final Button clearFilterButton = new Button("Clear Filter");
		final Button addFilterButton = new Button("Add Filter");

		clearFilterButton.setWidth("*");
		clearFilterButton.setHeight(40);
		clearFilterButton.setWrap(true);
		clearFilterButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				grid.setCriteria(null);
				clearFilterButton.hide();
				addFilterButton.show();
			}
		});
		
		buttonBar.addMember(clearFilterButton);
		
		addFilterButton.setWidth("*");
		addFilterButton.setHeight(40);
		addFilterButton.setWrap(true);
		addFilterButton.setVisible(false);
		addFilterButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				AdvancedCriteria criteria = new AdvancedCriteria("contentField", OperatorId.NOT_CONTAINS, " - update");
				grid.setCriteria(criteria);
				clearFilterButton.show();
				addFilterButton.hide();
			}
		});
		
		buttonBar.addMember(addFilterButton);
		
		final Button clearHilitesButton = new Button("Clear Hilites");
		final Button addHilitesButton = new Button("Add Hilites");
		final Button customHilitingButton = new Button("Custom Hilites");

		clearHilitesButton.setWidth("*");
		clearHilitesButton.setHeight(40);
		clearHilitesButton.setWrap(true);
		clearHilitesButton.setVisible(false);
		clearHilitesButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				customHiliting = false;
				grid.setHilites((Hilite[])null);
				clearHilitesButton.hide();
				addHilitesButton.show();
				customHilitingButton.show();
				if (timer != null) {
					timer.cancel();
					timer = null;
				}
			}
		});
		
		buttonBar.addMember(clearHilitesButton);
		
		addHilitesButton.setWidth("*");
		addHilitesButton.setHeight(40);
		addHilitesButton.setWrap(true);
		addHilitesButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				customHiliting = false;
				grid.setHilites(hilites);
				clearHilitesButton.show();
				addHilitesButton.hide();
				customHilitingButton.show();
				timer = new Timer() {
					@Override
					public void run() {
						grid.setHilites(grid.getHilites());
						timer.schedule(10 * 1000);
					}
				};
				timer.schedule(10 * 1000);
			}
		});
		
		buttonBar.addMember(addHilitesButton);

		customHilitingButton.setWidth("*");
		customHilitingButton.setHeight(40);
		customHilitingButton.setWrap(true);
		customHilitingButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				grid.setHilites((Hilite[])null);
				clearHilitesButton.show();
				addHilitesButton.show();
				customHilitingButton.hide();
				customHiliting = true;
				grid.markForRedraw();
				timer = new Timer() {
					@Override
					public void run() {
						grid.markForRedraw();
						timer.schedule(10 * 1000);
					}
				};
				timer.schedule(10 * 1000);
			}
		});
		
		buttonBar.addMember(customHilitingButton);
		
		addMember(buttonBar);
	}


	protected void showTime(Date start) {
		Window.alert("Time: " + (new Date().getTime() - start.getTime()));
	}
	
}
