package com.sbs.jpm.client;

import java.util.Date;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.ui.RootPanel;
import com.smartgwt.client.data.AdvancedCriteria;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSProtocol;
import com.smartgwt.client.types.FieldType;
import com.smartgwt.client.types.OperatorId;
import com.smartgwt.client.util.JSOHelper;
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.ListGridRecord;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeGridField;
import com.smartgwt.client.widgets.tree.TreeNode;
import com.smartgwt.client.widgets.tree.events.DataArrivedEvent;
import com.smartgwt.client.widgets.tree.events.DataArrivedHandler;

public class TestCase implements EntryPoint {

	private WBSPanel wbsPanel;
	private TaskDataSource dataSource;

	public void onModuleLoad() {

		dataSource = new TaskDataSource();

		wbsPanel = new WBSPanel();
		wbsPanel.setWidth100();
		wbsPanel.setHeight100();

		RootPanel.get().add(wbsPanel);

	}

	public class WBSPanel extends VLayout {

		private Button addToolbarButton;
		private Button filterButton;

		private TreeGrid tasksTreeGrid;
		private TreeGridField uidTreeGridField;
		private TreeGridField nameTreeGridField;
		private TreeGridField parentTreeGridField;

		public WBSPanel() {

			addToolbarButton = new Button();
			addToolbarButton.setTitle("Add");
			addToolbarButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					// adding a task into Project 1
					ListGridRecord newTaskt = new ListGridRecord();
					newTaskt.setAttribute(TaskDataSource.NAME_FIELD, "New task");
					newTaskt.setAttribute(TaskDataSource.PARENT_UNIQUE_ID, "p1");
					newTaskt.setAttribute(TaskDataSource.UNIQUE_ID_FIELD,
							new Date().getTime());

					tasksTreeGrid.addData(newTaskt);
				}
			});

			filterButton = new Button();
			filterButton.setTitle("Filter");
			filterButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					// showing only the task that belong to Project 1
					AdvancedCriteria criteria = new AdvancedCriteria(
							TaskDataSource.PARENT_UNIQUE_ID, OperatorId.EQUALS,
							"p1");

					// if we apply another filter that will show only the
					// Project 1 and its descendants then everything it's
					// working as expected - see the criteria below
					// AdvancedCriteria criteria = new AdvancedCriteria(
					// TaskDataSource.UNIQUE_ID_FIELD, OperatorId.NOT_EQUAL,
					// "root");
					tasksTreeGrid.filterData(criteria);

				}
			});

			uidTreeGridField = new TreeGridField();
			uidTreeGridField.setName(TaskDataSource.UNIQUE_ID_FIELD);
			uidTreeGridField.setTitle("UID");

			nameTreeGridField = new TreeGridField();
			nameTreeGridField.setName(TaskDataSource.NAME_FIELD);
			nameTreeGridField.setTitle("Task Name");
			nameTreeGridField.setTreeField(true);

			parentTreeGridField = new TreeGridField();
			parentTreeGridField.setName(TaskDataSource.PARENT_UNIQUE_ID);
			parentTreeGridField.setTitle("Parent");

			tasksTreeGrid = new TreeGrid();
			tasksTreeGrid.setWidth100();
			tasksTreeGrid.setHeight100();
			tasksTreeGrid.setDataSource(dataSource);
			tasksTreeGrid.setTreeRootValue("root");
			tasksTreeGrid.setLoadDataOnDemand(false);
			tasksTreeGrid.fetchData();
			tasksTreeGrid.setFields(nameTreeGridField, uidTreeGridField,
					parentTreeGridField);
			tasksTreeGrid.addDataArrivedHandler(new DataArrivedHandler() {
				@Override
				public void onDataArrived(DataArrivedEvent event) {
					tasksTreeGrid.getTree().openAll();
				}
			});

			this.setMembers(addToolbarButton, filterButton, tasksTreeGrid);
		}
	}

	public class TaskTreeNode extends TreeNode {

		public TaskTreeNode(String taskId, String reportsTo, String name) {
			setTaskId(taskId);
			setReportsTo(reportsTo);
			setName(name);
		}

		public void setTaskId(String value) {
			setAttribute(TaskDataSource.UNIQUE_ID_FIELD, value);
		}

		public void setReportsTo(String value) {
			setAttribute(TaskDataSource.PARENT_UNIQUE_ID, value);
		}

		public void setName(String name) {
			setAttribute(TaskDataSource.NAME_FIELD, name);
		}
	}

	public class TaskDataSource extends GwtRpcDataSource {
		private static final String DS_UNIQUE_ID = "_TaskDataSource";

		public static final String PARENT_UNIQUE_ID = "parentUniqueId"
				+ DS_UNIQUE_ID;
		public static final String UNIQUE_ID_FIELD = "uniqueIdField"
				+ DS_UNIQUE_ID;
		public static final String NAME_FIELD = "nameField" + DS_UNIQUE_ID;

		private TaskDataSource() {

			DataSourceField uniqueId = new DataSourceField();
			uniqueId.setName(UNIQUE_ID_FIELD);
			uniqueId.setPrimaryKey(true);
			uniqueId.setType(FieldType.TEXT);

			DataSourceField reportsToField = new DataSourceField();
			reportsToField.setName(PARENT_UNIQUE_ID);
			reportsToField.setForeignKey(DS_UNIQUE_ID + "." + UNIQUE_ID_FIELD);
			reportsToField.setType(FieldType.TEXT);

			this.setID(DS_UNIQUE_ID);
			this.setFields(uniqueId, reportsToField);
			this.setCacheAllData(true);
			this.setCacheMaxAge(3600);
		}

		@Override
		protected void executeFetch(final String requestId, DSRequest request,
				final DSResponse response) {

			TaskTreeNode root = new TaskTreeNode("root", null, "All Projects");
			TaskTreeNode node2 = new TaskTreeNode("p1", "root", "Project 1");
			TaskTreeNode node3 = new TaskTreeNode("t1", "p1", "Task 1");
			TaskTreeNode node4 = new TaskTreeNode("t2", "p1", "Task 2");

			response.setData(new TreeNode[] { root, node2, node3, node4 });
			response.setStatus(RPCResponse.STATUS_SUCCESS);
			response.setInvalidateCache(true);
			processResponse(requestId, response);
		}

		@Override
		protected void executeAdd(final String requestId, DSRequest request,
				final DSResponse response) {

			final ListGridRecord editedRecord = getEditedRecord(request);
			response.setData(editedRecord);
			response.setStatus(RPCResponse.STATUS_SUCCESS);
			processResponse(requestId, response);
		}

		@Override
		protected void executeUpdate(final String requestId,
				final DSRequest request, final DSResponse response) {
		}

		@Override
		protected void executeRemove(final String requestId, DSRequest request,
				final DSResponse response) {
		}
	}

	public abstract class GwtRpcDataSource extends DataSource {

		public GwtRpcDataSource() {
			setDataProtocol(DSProtocol.CLIENTCUSTOM);
			setDataFormat(DSDataFormat.CUSTOM);
			setClientOnly(false);
		}

		@Override
		protected Object transformRequest(DSRequest request) {
			String requestId = request.getRequestId();
			DSResponse response = new DSResponse();
			response.setAttribute("clientContext",
					request.getAttributeAsObject("clientContext"));
			response.setStatus(0);

			switch (request.getOperationType()) {
			case FETCH:
				executeFetch(requestId, request, response);
				break;
			case ADD:
				executeAdd(requestId, request, response);
				break;
			case UPDATE:
				executeUpdate(requestId, request, response);
				break;
			case REMOVE:
				executeRemove(requestId, request, response);
				break;
			default:
				break;
			}
			return request.getData();
		}

		protected abstract void executeFetch(String requestId,
				DSRequest request, DSResponse response);

		protected abstract void executeAdd(String requestId, DSRequest request,
				DSResponse response);

		protected abstract void executeUpdate(String requestId,
				DSRequest request, DSResponse response);

		protected abstract void executeRemove(String requestId,
				DSRequest request, DSResponse response);

	}

	protected ListGridRecord getEditedRecord(DSRequest request) {
		ListGridRecord newRecord = new ListGridRecord();
		newRecord = getOldRecord(request);
		JavaScriptObject data = request.getData();
		JSOHelper.apply(data, newRecord.getJsObj());
		return newRecord;
	}

	protected ListGridRecord getOldRecord(DSRequest request) {
		JavaScriptObject oldValues = request
				.getAttributeAsJavaScriptObject("oldValues");
		ListGridRecord oldRecord = new ListGridRecord();
		JSOHelper.apply(oldValues, oldRecord.getJsObj());
		return oldRecord;
	}
}
