package eu.dnetlib.client.managers;

import java.util.logging.Logger;

import javax.inject.Inject;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Singleton;
import com.sencha.gxt.widget.core.client.Dialog.PredefinedButton;
import com.sencha.gxt.widget.core.client.box.MessageBox;

import eu.dnetlib.client.GreetingService;
import eu.dnetlib.client.GreetingServiceAsync;
import eu.dnetlib.client.notification.NotificationSender;
import eu.dnetlib.client.updaters.Updater;
import eu.dnetlib.efg1914.authoring.components.Configuration;
import eu.dnetlib.efg1914.authoring.components.Frame;
import eu.dnetlib.efg1914.authoring.components.Item;
import eu.dnetlib.efg1914.authoring.components.Theme;
import eu.dnetlib.efg1914.authoring.components.Topic;
import eu.dnetlib.efg1914.authoring.users.User;

@Singleton
public class UpdateManagerImpl implements UpdateManager {

	@Inject
	private Updater updater;

	@Inject
	private ActiveComponentsManager activeComponentsManager;
	@Inject
	private NotificationSender notificationSender;

	private GreetingServiceAsync greetingService;

	private static Logger log = Logger.getLogger("UpdateManager.java");

	@Inject
	UpdateManagerImpl() {
		greetingService = GWT.create(GreetingService.class);

	}

	public void createNewItem(final User user, Item itemToSave) {
		this.greetingService.createNewItem(user, itemToSave, new AsyncCallback<Item>() {

			public void onSuccess(Item item) {

				updater.createNewItem(user.getId(), item, true);
				notificationSender.sendNewItem(item);

				log.info("Item created!!!");
			}

			public void onFailure(Throwable caught) {
				log.warning(" Error creating new item" + caught.getMessage());
				warningBox(" Error creating new item").show();
				updater.itemFails(true);
			}
		});

	}

	public void updateItem(final Item item, final String userId) {
		greetingService.updateItem(item, new AsyncCallback<Item>() {

			public void onSuccess(Item updatedItem) {
				updater.updateItem(updatedItem, userId, true);

				notificationSender.sendUpdatedItem(updatedItem);

				activeComponentsManager.unMarkItem(updatedItem.getId(), userId);

			}

			public void onFailure(Throwable caught) {
				log.warning(" Error updating item" + caught.getMessage());
				warningBox(" Error updating  item").show();
				updater.itemFails(true);

			}
		});
	}

	public void deleteItem(final Item item, final String userId) {
		greetingService.deleteItem(item, new AsyncCallback<String>() {

			public void onSuccess(String arg0) {
				log.info(" item   deletion sucess");

				updater.deleteItem(item, userId, true);

				notificationSender.sendDeletedItem(item);

			}

			public void onFailure(Throwable caught) {
				log.info(" item deletion  failed" + caught.getMessage());
				warningBox(" Error deleting  item").show();
				updater.itemFails(true);
			}

		});

	}

	public void createNewFrame(final String userId, final Frame frame) {

		greetingService.saveFrame(frame, new AsyncCallback<String>() {

			public void onSuccess(String frameID) {
				frame.setId(frameID);
				updater.createNewFrame(userId, frame, true);
				log.info("created frame" + frame.toString());
				notificationSender.sendNewFrame(frame);

			}

			public void onFailure(Throwable arg0) {

				log.warning("FAIL TO SAVE FRAME");
				warningBox(" Error creating new frame").show();
				updater.frameFails(true);

			}
		});

	}

	public void updateFrame(final Frame updatedFrame, final String userId) {
		greetingService.updateFrame(updatedFrame, new AsyncCallback<String>() {

			public void onSuccess(String res) {
				updater.updateFrame(updatedFrame, userId, true);

				notificationSender.sendUpdatedFrame(updatedFrame);

				activeComponentsManager.unMarkItem(updatedFrame.getId(), userId);

			}

			public void onFailure(Throwable caught) {
				log.warning(" Error updating frame" + caught.getMessage());
				warningBox(" Error updating  frame").show();
				updater.frameFails(true);

			}
		});
	}

	public void deleteFrame(final Frame frame, final String userId) {
		log.warning("on delete frame");
		greetingService.deleteFrame(frame.getId(), new AsyncCallback<String>() {

			public void onSuccess(String arg0) {
				log.info(" frame   deletion sucess");

				updater.deleteFrame(frame, userId, true);
				notificationSender.sendDeletedFrame(frame);

			}

			public void onFailure(Throwable caught) {
				log.warning(" frame deletion  failed" + caught.getMessage());
				warningBox(" Error deleting  frame").show();
				updater.frameFails(true);

			}

		});

	}

	public void createNewTopic(final String userId, final Topic topic) {
		greetingService.saveAndGetTopic(topic, new AsyncCallback<Topic>() {

			public void onSuccess(Topic newTopic) {
				updater.createNewTopic(userId, newTopic, true);

				notificationSender.sendNewTopic(newTopic);

			}

			public void onFailure(Throwable arg0) {
				log.warning("FAIL TO SAVE topic");
				warningBox(" Error creating new topic ").show();
				updater.topicFails(true);

			}
		});

	}

	public void updateTopic(final Topic updatedTopic, final String userId) {
		greetingService.updateTopic(updatedTopic, new AsyncCallback<String>() {

			public void onSuccess(String res) {

				updater.updateTopic(updatedTopic, userId, true);
				notificationSender.sendUpdatedTopic(updatedTopic);

				activeComponentsManager.unMarkItem(updatedTopic.getId(), userId);

			}

			public void onFailure(Throwable caught) {
				log.warning(" Error updating item" + caught.getMessage());
				warningBox(" Error updating  topic").show();
				updater.topicFails(true);

			}
		});
	}

	public void deleteTopic(final Topic topic, final String userId) {
		greetingService.deleteTopic(topic.getId(), new AsyncCallback<String>() {

			public void onSuccess(String arg0) {
				log.info(" Topic   deletion sucess");
				updater.deleteTopic(topic, userId, true);

				notificationSender.sendDeletedTopic(topic);

			}

			public void onFailure(Throwable caught) {
				log.warning(" topic deletion  failed" + caught.getMessage());
				warningBox(" Error deleting  topic").show();
				updater.topicFails(true);

			}

		});

	}

	public void createNewTheme(final String userId, final Theme theme) {
		greetingService.saveTheme(theme, new AsyncCallback<Theme>() {

			public void onSuccess(Theme newTheme) {
				updater.createNewTheme(userId, newTheme, true);

				notificationSender.sendNewTheme(newTheme);
				 greetingService.getConfigurationByName("EFG1914", new AsyncCallback<Configuration>() {
						
						public void onSuccess(Configuration configuration) {
							updater.updateConfiguration(configuration, userId, false);

							notificationSender.sendupdatedConfiguration(configuration);						
						}
						
						public void onFailure(Throwable caught) {
 
						}
					});

			}

			public void onFailure(Throwable arg0) {

				log.warning("FAIL TO SAVE topic");
				warningBox(" Error creating new theme ").show();
				updater.themeFails(true);

			}
		});

	}

	public void updateTheme(final Theme updatedTheme, final String userId) {
		greetingService.updateTheme(updatedTheme, new AsyncCallback<String>() {

			public void onSuccess(String res) {
				updater.updateTheme(updatedTheme, userId, true);
				notificationSender.sendUpdatedTheme(updatedTheme);

				activeComponentsManager.unMarkItem(updatedTheme.getId(), userId);
				 greetingService.getConfigurationByName("EFG1914", new AsyncCallback<Configuration>() {
						
						public void onSuccess(Configuration configuration) {
							updater.updateConfiguration(configuration, userId, false);

							notificationSender.sendupdatedConfiguration(configuration);						
						}
						
						public void onFailure(Throwable arg0) {
							// TODO Auto-generated method stub
							
						}
					});
				 
			}

			public void onFailure(Throwable caught) {
				log.warning(" Error updating item" + caught.getMessage());
				warningBox(" Error updating   theme ").show();
				updater.themeFails(true);

			}
		});
	}

	public void deleteTheme(final Theme theme, final String userId) {
		greetingService.deleteTheme(theme, new AsyncCallback<String>() {

			public void onSuccess(String arg0) {
				log.warning(" frame   deletion sucess");

				updater.deleteTheme(theme, userId, true);

				notificationSender.sendDeletedTheme(theme);
				 greetingService.getConfigurationByName("EFG1914", new AsyncCallback<Configuration>() {
					
					public void onSuccess(Configuration configuration) {
						updater.updateConfiguration(configuration, userId, false);

						notificationSender.sendupdatedConfiguration(configuration);						
					}
					
					public void onFailure(Throwable arg0) {
					 

					}
				});

			}

			public void onFailure(Throwable caught) {
				log.warning(" frame deletion  failed" + caught.getMessage());
				warningBox(" Error deleting theme ").show();
				updater.themeFails(true);
			}

		});

	}

	public void createUser(final User userToCreate, final String userId) {
		greetingService.saveUser(userToCreate, new AsyncCallback<String>() {

			public void onSuccess(String id) {
				userToCreate.setId(id);
				updater.createUser(userToCreate, userId, true);

				log.info("user created in db!!!");

				notificationSender.sendNewUser(userToCreate);
			}

			public void onFailure(Throwable caught) {
				log.warning(" Error creating user" + caught.getMessage());
				warningBox(" Error creating user ").show();
				updater.userFails(true);

			}
		});

	}

	public void updateUser(final User userToUpdate, final String userId) {
		greetingService.updateUser(userToUpdate, new AsyncCallback<String>() {

			public void onSuccess(String arg0) {
				log.info("User Profile updated!");
				updater.updateUser(userToUpdate, userId, true);

				notificationSender.sendUpdatedUser(userToUpdate);
			}

			public void onFailure(Throwable caught) {
				log.warning(" Error updating user" + caught.getMessage());
				warningBox(" Error updating user ").show();
				updater.userFails(true);
			}
		});

	}

	public void deleteUser(final String userIdToDelete, final String userId) {
		greetingService.deleteUser(userIdToDelete, new AsyncCallback<Void>() {

			public void onSuccess(Void arg0) {
				log.info("user deleted !!!");
				updater.deleteUser(userIdToDelete, userId, true);

				notificationSender.sendDeletedUser(userIdToDelete);
			}

			public void onFailure(Throwable caught) {
			 
				log.warning(" Error deleting user with id " + userIdToDelete + caught.getMessage());
				warningBox(" Error deleting user ").show();
				updater.userFails(true);

			}
		});

	}

	public void updateConfiguration(final Configuration configuration, final String userId) {
		greetingService.updateConfiguration(configuration, new AsyncCallback<Void>() {

			public void onSuccess(Void arg0) {

				updater.updateConfiguration(configuration, userId, true);

				notificationSender.sendupdatedConfiguration(configuration);
			}

			public void onFailure(Throwable caught) {
				 
				log.warning(" Error   " + caught.getMessage());
				updater.configurationFails(true);
			}
		});

	}

	public MessageBox warningBox(String message) {
		final MessageBox warning = new MessageBox(" Warning", message);

		warning.setPredefinedButtons(PredefinedButton.OK);
		warning.setIcon(MessageBox.ICONS.warning());
		warning.setMinHeight(100);

		return warning;
	}

}
