package net.fina.auditlog.client;

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

import net.fina.auditlog.shared.AuditLog;

import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class App implements EntryPoint {

	private final Messages messages = GWT.create(Messages.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		// Create a CellTable.
		final CellTable<AuditLog> table = new CellTable<AuditLog>();
		table.setPageSize(20);

		// Add a text column to show the name.
		TextColumn<AuditLog> id = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getId() + "";
			}
		};
		table.addColumn(id, "id");

		DateTimeFormat format = DateTimeFormat
				.getFormat("dd.MM.yyyy-hh:mm:ss.SSS");
		DateCell dateCell = new DateCell(format);
		Column<AuditLog, Date> revelenceTime = new Column<AuditLog, Date>(
				dateCell) {
			@Override
			public Date getValue(AuditLog object) {
				return object.getRelevanceTime();
			}
		};
		table.addColumn(revelenceTime, "Revelence Time");

		TextColumn<AuditLog> actorId = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getActorId();
			}
		};
		table.addColumn(actorId, "Actor Id");

		TextColumn<AuditLog> entityId = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getEntityId();
			}
		};
		table.addColumn(entityId, "Entity Id");

		TextColumn<AuditLog> entityName = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getEntityName();
			}
		};
		table.addColumn(entityName, "Entity Name");

		TextColumn<AuditLog> entityProperty = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getEntityProperty();
			}
		};
		table.addColumn(entityProperty, "Entity Property");

		TextColumn<AuditLog> entityPropertyNewValue = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getEntityPropertyNewValue();
			}
		};
		table.addColumn(entityPropertyNewValue, "Entity Property New Value");

		TextColumn<AuditLog> entityPropertyOldValue = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getEntityPropertyOldValue();
			}
		};
		table.addColumn(entityPropertyOldValue, "Entity Property Old Value");

		TextColumn<AuditLog> operationType = new TextColumn<AuditLog>() {
			@Override
			public String getValue(AuditLog object) {
				return object.getOperationType() + "";
			}
		};
		table.addColumn(operationType, "Operation Type");

		final AsyncDataProvider<AuditLog> provider = new AsyncDataProvider<AuditLog>() {
			@Override
			protected void onRangeChanged(HasData<AuditLog> display) {

				final int start = display.getVisibleRange().getStart();
				int length = display.getVisibleRange().getLength();
				AsyncCallback<List<AuditLog>> callback = new AsyncCallback<List<AuditLog>>() {
					@Override
					public void onFailure(Throwable caught) {
						Window.alert(caught.getMessage());
					}

					@Override
					public void onSuccess(List<AuditLog> result) {
						updateRowData(start, result);
					}
				};
				GreetingServiceAsync.Util.getInstance()
						.fetchPage(
								start,
								length,
								actorIdTextBox == null ? "" : actorIdTextBox
										.getValue(),
								startDateBox == null ? null : startDateBox
										.getValue(),
								endDateBox == null ? null : endDateBox
										.getValue(), callback);
			}
		};
		provider.addDataDisplay(table);
		updateRowCount(provider);

		final SimplePager pager = new SimplePager();
		pager.setDisplay(table);

		HorizontalPanel hPanel = new HorizontalPanel();
		hPanel.setSpacing(5);

		// Add some content to the panel
		Label actorIdLabel = new Label("Actor Id");
		hPanel.add(actorIdLabel);
		hPanel.add(actorIdTextBox);

		// Create a DateBox
		startDateBox.setFormat(new DateBox.DefaultFormat(format));
		startDateBox.getDatePicker().setYearArrowsVisible(true);

		// Create a DateBox
		endDateBox.setFormat(new DateBox.DefaultFormat(format));
		endDateBox.getDatePicker().setYearArrowsVisible(true);

		hPanel.add(new Label("Start"));
		hPanel.add(startDateBox);
		hPanel.add(new Label("End"));
		hPanel.add(endDateBox);

		final Button filterButton = new Button("Filter");
		filterButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				filterButton.setEnabled(false);
				try {
					if (pager.getPage() > 0) {
						pager.nextPage();
						pager.setPage(pager.getPage() - 1);
					}
					updateRowCount(provider);
					table.redraw();
				} finally {
					filterButton.setEnabled(true);
				}
			}
		});
		hPanel.add(filterButton);

		VerticalPanel vp = new VerticalPanel();
		vp.add(hPanel);
		vp.add(table);
		vp.add(pager);

		// Add it to the root panel.
		RootPanel.get().add(vp);
	}

	private void updateRowCount(final AsyncDataProvider<AuditLog> provider) {
		GreetingServiceAsync.Util.getInstance().count(
				actorIdTextBox == null ? "" : actorIdTextBox.getValue(),
				startDateBox == null ? null : startDateBox.getValue(),
				endDateBox == null ? null : endDateBox.getValue(),
				new AsyncCallback<Long>() {

					@Override
					public void onFailure(Throwable caught) {
						Window.alert(caught.getMessage());
					}

					@Override
					public void onSuccess(Long result) {
						provider.updateRowCount((int) ((long) result), true);
					}
				});
	}

	private TextBox actorIdTextBox = new TextBox();
	private DateBox startDateBox = new DateBox();
	private DateBox endDateBox = new DateBox();
}
