//	Contour - Android drawing teacher application
//	Copyright (C) 2014  Johannes Riedmann
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//	
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//	
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.

package com.j0h1.contour.admin.client;

import java.util.ArrayList;

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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Button;
import com.j0h1.contour.admin.client.service.ImageService;
import com.j0h1.contour.admin.client.service.ImageServiceAsync;
import com.j0h1.contour.admin.client.service.TrackService;
import com.j0h1.contour.admin.client.service.TrackServiceAsync;
import com.j0h1.contour.admin.shared.domain.Image;
import com.j0h1.contour.admin.shared.domain.Track;

/**
 * View that contains the UI elements and logic to add a new track.
 * @author Johannes Riedmann
 *
 */
public class AddTrackView extends Composite {

	private static AddTrackViewUiBinder uiBinder = GWT
			.create(AddTrackViewUiBinder.class);
	
	@UiField TextBox txtTitleEN;
	@UiField TextBox txtTitleDE;
	@UiField FlexTable ftbAddImages;
	@UiField Button btnSave;
	@UiField Label lblStatus;
	
	private int rowCount;

	interface AddTrackViewUiBinder extends UiBinder<Widget, AddTrackView> {
		
	}

	public AddTrackView() {
		initWidget(uiBinder.createAndBindUi(this));
		
		refreshData();
	}
	
	private void setFlexTableHeaderData() {
		ftbAddImages.setText(0, 0, "Title (en)");
		ftbAddImages.setText(0, 1, "Add");
		if (rowCount == 1) {
			if (ftbAddImages.getCellCount(0) == 3) {
				ftbAddImages.removeCell(0, 2);
			}
		}
		if (rowCount > 1) {
			ftbAddImages.setText(0, 2, "Remove");
		}
	}
	
	public void refreshData() {
		ftbAddImages.removeAllRows();
		
		rowCount = 1;
		
		// calling service to receive List of all non-deleted images and handling callback 
		ImageServiceAsync imageService = GWT.create(ImageService.class);

		AsyncCallback<ArrayList<Image>> callback = new AsyncCallback<ArrayList<Image>>() {
			public void onFailure(Throwable caught) {
				// should work out just fine when database server is started
			}

			public void onSuccess(ArrayList<Image> result) {
				populateFlexTable(result);
			}
		};

		imageService.findAll(callback);
	}
	
	private void populateFlexTable(final ArrayList<Image> images) {
		setFlexTableHeaderData();
		
		// populate ListBox with english image names (value set to imageId)
		ListBox imagesCombo = new ListBox();
		imagesCombo.setWidth("200px");
		for (int i = 0; i < images.size(); i++) {
			imagesCombo.insertItem(images.get(i).getTitleEN(), 
					String.valueOf(images.get(i).getImageId()), i);
		}
		
		// Button to add another image to the Track
		Button addAnotherImageButton = new Button("+");
		addAnotherImageButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {					
				rowCount++;
				populateFlexTable(images);
			}			
		});
		
		// Button to remove an image from the track
		Button removeAnImageButton = new Button("-");
		removeAnImageButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				rowCount--;
				ftbAddImages.removeRow(ftbAddImages
						.getCellForEvent(event).getRowIndex());
				
				// refresh header data since rowCount could be 1 at this point
				// which means that the "remove image" column must  be removed
				setFlexTableHeaderData();
			}			
		});
		
		// add Widgets to FlexTable
		ftbAddImages.setWidget(rowCount, 0, imagesCombo);
		ftbAddImages.setWidget(rowCount, 1, addAnotherImageButton);
		
		if (rowCount > 1) {
			ftbAddImages.setWidget(rowCount, 2, removeAnImageButton);
		}
	}
	
	@UiHandler("btnSave")
	public void saveTrack(ClickEvent e) {
		// check if titles are set
		if (txtTitleEN.getText().isEmpty() ||
				txtTitleDE.getText().isEmpty()) {
			setStatusLabel("Set a title for the track in german and english.", true);
			return;
		}
		
		// extract images from FlexTable
		if (ftbAddImages.getRowCount() == 1) {
			setStatusLabel("Please assign at least one image to the track.", true);
			return;
		}
		
		ArrayList<Image> images = new ArrayList<Image>();
		
		for (int i = 1; i < ftbAddImages.getRowCount(); i++) {
			ListBox tempBox = (ListBox) ftbAddImages.getWidget(i, 0);
			String titleEN = tempBox.getItemText(tempBox.getSelectedIndex());
			int imageId = Integer.valueOf(tempBox.getValue(tempBox.getSelectedIndex()));
			
			Image tempImage = new Image();
			tempImage.setTitleEN(titleEN);
			tempImage.setImageId(imageId);
			tempImage.setPosition(i);
			
			// if a image was accidently added twice
			boolean alreadyIn = false;
			for (int j = 0; j < images.size(); j++) {
				if (tempImage.getImageId() == images.get(j).getImageId()) {
					alreadyIn = true;
				}
			}
			
			if (!alreadyIn) {
				images.add(tempImage);
			}			
		}
		
		// create new track with given data
		Track track = new Track();
		track.setTitleEN(txtTitleEN.getText().trim());
		track.setTitleDE(txtTitleDE.getText().trim());
		track.setImages(images);
		
		// call remote service to persist track
		TrackServiceAsync trackService = GWT.create(TrackService.class);
		
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			@Override
			public void onFailure(Throwable caught) {
				setStatusLabel(caught.getMessage(), true);
			}

			@Override
			public void onSuccess(Void result) {
				setStatusLabel("Track successfully added.", false);
			}			
		};
		
		trackService.persist(track, callback);
	}
	
	/**
	 * Set the status label to a given text for feedback.
	 * @param text		Exception/success message.
	 * @param isError 	Flag that defines if the current message is a
	 * 					error message.
	 */
	private void setStatusLabel(String text, boolean isError) {
		lblStatus.setVisible(true);
		lblStatus.setText(text);
		
		if (isError) {
			lblStatus.getElement().getStyle().setColor("red");
		} else {
			lblStatus.getElement().getStyle().setColor("green");
		}
		
		Timer t = new Timer() {
			public void run() {
				lblStatus.setVisible(false);
			}
		};

		t.schedule(3000);
	}

}
