package eu.dnetlib.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import eu.dnetlib.client.GreetingService;
import eu.dnetlib.client.shared.StartUpComponents;
import eu.dnetlib.efg1914.authoring.components.Frame;
import eu.dnetlib.efg1914.authoring.components.Item;
import eu.dnetlib.efg1914.authoring.components.Permit;
import eu.dnetlib.efg1914.authoring.components.Theme;
import eu.dnetlib.efg1914.authoring.components.Topic;
import eu.dnetlib.efg1914.authoring.managers.ComponentManager;
import eu.dnetlib.efg1914.authoring.managers.ComponentManagerException;
import eu.dnetlib.efg1914.authoring.managers.MediaManager;
import eu.dnetlib.efg1914.authoring.managers.UserManager;
import eu.dnetlib.efg1914.authoring.managers.UserManagerException;
import eu.dnetlib.efg1914.authoring.users.User;
import eu.dnetlib.efg1914.commons.store.XMLStoreException;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
@Service("greetingService")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
	@Autowired
	private ComponentManager componentManager;
	@Autowired
	private MediaManager mediaManager;
	@Autowired
	private UserManager userManager;

	@Autowired
	private String mongopath;
	@Autowired
	private Integer maxfilesize;

	private static Logger log = Logger.getLogger("greetingServiceImpl");

	public String sendItemServer(Item item) throws XMLStoreException {
		String id = item.getTitle();
		return id;
	}

	/*************************
	 * GET COMPONENTS FROM DB ON STARTUP
	 * 
	 * @throws XMLStoreException
	 * *********************************/

	public GreetingServiceImpl() {

	}

	public StartUpComponents loadComponents(User user) throws XMLStoreException {
		StartUpComponents comp = new StartUpComponents();
		comp.setMaxFileSize(this.maxfilesize);
		comp.setServerPath(this.mongopath);
		comp.setUser(user);
		log.info("user " + user.toString());
		try {
			// ####################### ITEMS ######################
			comp.setAllItems(this.componentManager.getAllItemsMap());

			log.info(" all items" + comp.getAllItems().size());

			// ####################### Frames ######################
			comp.setAllFrames(this.componentManager.getAllFramesMap());
			log.info(" all frames" + comp.getAllFrames().size());

			// ####################### Topics ######################
			comp.setAllTopics(this.componentManager.getAllTopicsMap());
			log.info(" all topics" + comp.getAllTopics().size());

			// ####################### Themes ######################
			comp.setAllThemes(this.componentManager.getAllThemesMap());

			// TODO added perms for creatrion

			log.info(" all themes" + comp.getAllThemes().size());

			comp.setPermissions(loadPermissions(user.getUsername()));

			// ####################### Archives ######################
			comp.setArchives(componentManager.getArchivesMap());
			log.info("archives" + comp.getArchives());
			// ####################### Curators ######################
			comp.setCurators(userManager.getCurators());
			log.info("curators" + comp.getCurators());
		} catch (ComponentManagerException e) {

			throw new XMLStoreException(e.toString(), e);
		} catch (UserManagerException e) {
			throw new XMLStoreException(e.toString(), e);

		}
		return comp;
	}

	/*******************************************************
	 * ITEMS
	 ******************************************************/

	public Item createNewItem(User user, Item itemToSave) throws XMLStoreException {
		try {
			log.info(" Create   new   ITEM!! ");
			Item it = this.componentManager.createNewItem(itemToSave);

			log.info(" CREATED ITEM id: " + it.getId());

			return it;
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			// StackTraceElement[] trace = e.getStackTrace();

			// throw new XMLStoreException(trace[trace.length].toString()) {
			// };

			throw new XMLStoreException(e);
		}

	}

	public Item fetchItemMetadata(String url) throws XMLStoreException {
		try {
			return this.componentManager.fetchItemMetadata(url);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException();
		}

	}

	public Item createNewImageItemFromID(User user, String url, String filetype, String mediaID) throws XMLStoreException {

		try {
			log.info(" Create   new   ITEM!! ");
			Item it = this.componentManager.createNewImageItem(user, url, filetype, mediaID);

			log.info(" CREATED ITEM id: " + it.getId());

			return it;
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public Item createNewVideoItem(User user, String filetype, String url, String mediaId) throws XMLStoreException {
		log.info(" Create  new ITEM from metadata !! ");

		try {
			Item it = this.componentManager.createNewVideoItem(user, filetype, url, mediaId);
			log.info("CREATED ITEM id: " + it.getId());
			return it;
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public ArrayList<Item> getAllItems() throws XMLStoreException {

		try {
			ArrayList<Item> items = this.componentManager.getAllItems();

			return items;
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public Item getItemById(String itemId) throws XMLStoreException {
		log.info("Get  ITEM!! ");

		try {
			Item item = this.componentManager.getItem(itemId);
			return item;
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public boolean updateItemMetadata(Item item) throws XMLStoreException {
		log.info("Update ITEM   !! ");

		try {
			return this.componentManager.updateItem(item);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public String deleteItem(Item item) throws XMLStoreException {
		log.info(" Removing ITEM   !! ");

		try {
			this.componentManager.deleteItem(item);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
		return "done";
	}

	public String deleteMedia(String mediaId) throws XMLStoreException {
		log.info(" Removing ITEM MEDIA !! ");
		this.mediaManager.deleteMediaFile(mediaId);

		return "done";
	}

	public Item updateItem(Item item) throws XMLStoreException {
		log.info("Update  whole Item ! ");

		try {
			this.componentManager.updateItem(item);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException("Item and thumb update failed " + e.toString());
		}

		return item;

	}

	public Item updateItem(Item item, String miniId, String mediumId, String thumbFileType, boolean isThumbChanged)
			throws XMLStoreException {

		log.info("Update   Item  with new images! ");

		try {

			if (isThumbChanged)

			{

				if (miniId == null || miniId.isEmpty()) {
					log.info("Without mini ");

				}
				if (mediumId == null || mediumId.isEmpty()) {
					log.info("Without medium ");

				}
				item.setMediumImage(mediumId);
				item.setMiniImage(miniId);

			}

			this.componentManager.updateItem(item);

		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException("Item and thumb update failed");

		}
		return item;

	}

	public List<String> getItemParents(String itemId) throws XMLStoreException {
		return this.componentManager.getItemParentsIds(itemId);

	}

	/*******************************************************
	 * FRAMES
	 ******************************************************/

	public String saveFrame(Frame frame) throws XMLStoreException {
		log.info("Save Frame!!");
		try {
			return this.componentManager.saveFrame(frame);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public List<Frame> getAllFrames() throws XMLStoreException {
		System.out.println("Get my ITEMs!! ");

		try {
			return this.componentManager.getAllFrames();

		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public Frame getFrameById(String frameId) throws XMLStoreException {
		System.out.println("Get my frame!! ");

		try {
			return this.componentManager.getFrame(frameId);

		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public String updateFrame(Frame frame) throws XMLStoreException {
		log.info("update frame ! ");

		try {
			this.componentManager.updateFrame(frame);
			return frame.getId();
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public String deleteFrame(String frameId) throws XMLStoreException {
		log.info("delete frame ! ");

		try {
			this.componentManager.deleteFrame(frameId);
			return "ok";
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public List<String> getFrameParents(String frameId) throws XMLStoreException {
		return this.componentManager.getFrameParentsIds(frameId);
	}

	/*******************************************************
	 * TOPICS
	 ******************************************************/

	public String saveTopic(Topic topic) throws XMLStoreException {

		try {
			return componentManager.saveTopic(topic);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public Topic saveAndGetTopic(Topic topic) throws XMLStoreException {

		try {
			String newTopicId = componentManager.saveTopic(topic);

			return componentManager.getTopic(newTopicId);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}
	}

	public String updateTopic(Topic t) throws XMLStoreException {

		try {
			componentManager.updateTopic(t);
			return " ok ";
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public String deleteTopic(String topicId) throws XMLStoreException {

		try {
			componentManager.deleteTopic(topicId);
			return " ok ";
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public List<String> getTopicParents(String topicId) throws XMLStoreException {
		return this.componentManager.getTopicParentsIds(topicId);
	}

	/*******************************************************
	 * THEMES
	 ******************************************************/
	public Theme saveTheme(Theme theme) throws XMLStoreException {

		try {
			String themeId = componentManager.saveTheme(theme);
			return componentManager.getTheme(themeId);
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public String updateTheme(Theme theme) throws XMLStoreException {

		try {
			componentManager.updateTheme(theme);
			return " ok ";
		} catch (ComponentManagerException e) {
			e.printStackTrace();
			log.warning("------------------****exception while updating theme  " + e.getMessage());
			throw new XMLStoreException(e);
		}

	}

	public String deleteTheme(Theme theme) throws XMLStoreException {

		try {
			componentManager.deleteTheme(theme);
			return " ok ";
		} catch (ComponentManagerException e) {
			e.printStackTrace();

			throw new XMLStoreException(e);
		}

	}

	/*******************************************************
	 * USER MANAGEMENT
	 * 
	 * @throws XMLStoreException
	 ******************************************************/

	public HashMap<String, Permit> loadPermissions(String username) throws XMLStoreException {

		try {
			return userManager.loadPermissions(username);

		} catch (UserManagerException e) {

			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public void registerUser(User user) throws XMLStoreException {
		log.info("Attempting to create new user..!!");

		try {
			this.userManager.registerUser(user);

		} catch (UserManagerException e) {
			throw new XMLStoreException("User registration for " + user.getUsername() + "failed", e);
		}

	}

	public String updateUser(User user) throws XMLStoreException {
		log.info("updating user..!!");

		try {
			this.userManager.updateUser(user);
			return "ok";
		} catch (UserManagerException e) {
			throw new XMLStoreException(e);
		}

	}

	public String getUserName(String userId) throws XMLStoreException {
		log.info("updating user..!!");

		try {
			return this.userManager.getCurator(userId);

		} catch (UserManagerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new XMLStoreException(e);
		}

	}

	public String getMediaServerPath() {

		return mongopath;
	}

	public Integer getMaxFileSize() {

		return maxfilesize;
	}

}
