package com.tootsville.tootsbook.server.util;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import org.starhope.appius.except.NotFoundException;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.game.inventory.Inventory;
import org.starhope.appius.game.inventory.InventoryItem;
import org.starhope.appius.game.inventory.InventoryItemType;
import org.starhope.appius.types.GameWorldMessage;
import org.starhope.appius.user.AbstractUser;
import org.starhope.appius.user.GeneralUser;
import org.starhope.appius.user.Nomenclator;
import org.starhope.appius.util.AppiusConfig;

import com.tootsville.tootsbook.client.util.AvailableItems;
import com.tootsville.tootsbook.client.util.Post;
import com.tootsville.tootsbook.client.util.ShadowUser;
import com.tootsville.tootsbook.client.util.ThemeItem;
import com.tootsville.tootsbook.client.util.UserProfile;
import com.tootsville.tootsbook.client.util.ThemeItem.ThemeItemType;
import com.tootsville.user.Toot;

/**
 * @author twheys@gmail.com
 */
public class Translator {

	/**
	 *
	 */
	private static final Logger logger = Logger
			.getLogger (Translator.class.getCanonicalName ());

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * To convert a buddy list we must iterate through a user list and
	 * validate (?) each entry . Certain names are special-cased because
	 * they are not allowed on a buddy list. Shade and any character
	 * starting with $ are not allowed on the buddy list.
	 * 
	 * @param buddyList a map of user ID:s to names
	 * @return a client-safe buddy list
	 */
	private static List <ShadowUser> convertBuddyList (
			final List <String> buddyList) {
		final List <ShadowUser> clientBuddyList = new LinkedList <ShadowUser> ();
		for (final String buddyUserName : buddyList) {
			final int buddyUserID = Nomenclator
					.getUserIDForLogin (buddyUserName);
			if ('$' != buddyUserName.charAt (0)
					&& !"Shade".equalsIgnoreCase (buddyUserName)) {
				final ShadowUser theClientUser = new ShadowUser (
						buddyUserID, buddyUserName);
				clientBuddyList.add (theClientUser);
				Translator.logger.finest ("Loaded ShadowUser ID#"
						+ buddyUserID + " in buddies.");
				theClientUser.setIcon (Translator
						.getIconForUser (buddyUserID));
			}
		}
		return clientBuddyList;
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getActiveAvatarBackground we must retrieve the active item
	 * from the serverUser. If there is no active item for that user,
	 * use the default instead.
	 * 
	 * @param serverUser The user who's inventory is being questioned.
	 * @param clientUser The same user as serverUser, except safe for
	 *            the client to use.
	 */
	private static void getActiveAvatarBackground (
			final AbstractUser serverUser, final UserProfile clientUser) {
		clientUser.setPageResource (Translator.getActiveItem (
				serverUser, clientUser, InventoryItemType
						.get ("tb-avatar-bg"), "avatarBG"));
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getActiveBoxStyle we must retrieve the active item from the
	 * serverUser. If there is no active item for that user, use the
	 * default instead.
	 * 
	 * @param serverUser The user who's inventory is being questioned.
	 * @param clientUser The same user as serverUser, except safe for
	 *            the client to use.
	 */
	private static void getActiveBoxStyle (
			final AbstractUser serverUser, final UserProfile clientUser) {
		clientUser.setBoxColorResource (Translator.getActiveItem (
				serverUser, clientUser, InventoryItemType
						.get ("tb-box-styles"), "boxColors"));
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getActiveIcon we must retrieve the active item from the
	 * serverUser. If there is no active item for that user, use the
	 * default instead.
	 * 
	 * @param serverUser The user who's inventory is being questioned.
	 * @param clientUser The same user as serverUser, except safe for
	 *            the client to use.
	 */
	private static void getActiveIcon (final AbstractUser serverUser,
			final UserProfile clientUser) {
		clientUser.setIcon (Translator.getActiveItem (serverUser,
				clientUser, InventoryItemType.get ("tb-icon"), "icon"));
	}

	/**
	 * WRITEME brpocock@star-hope.org Jul 30, 2010
	 * 
	 * @param serverUser WRITEME
	 * @param clientUser WRITEME
	 * @param type WRITEME
	 * @param defaultsKey WRITEME
	 * @return WRITEME
	 */
	private static String getActiveItem (final AbstractUser serverUser,
			final UserProfile clientUser, final InventoryItemType type,
			final String defaultsKey) {
		try {
			final InventoryItem item = serverUser.getInventory ()
					.getActiveItemByType (type);
			return String.valueOf (item.getGenericItem ().getItemID ());
		} catch (final NotFoundException e) {
			try {
				return String.valueOf (AppiusConfig
						.getInt ("com.tootsville.tootsbook.defaults."
								+ defaultsKey));
			} catch (final NumberFormatException e1) {
				throw AppiusClaudiusCaecus
						.fatalBug (
								"Unhandled NumberFormatException in getActiveItem",
								e1);
			} catch (final NotFoundException e1) {
				throw AppiusClaudiusCaecus.fatalBug (
						"Unhandled NotFoundException in getActiveItem",
						e1);
			}
		}
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getActivePageBackground we must retrieve the active item from
	 * the serverUser. If there is no active item for that user, use the
	 * default instead.
	 * 
	 * @param serverUser The user who's inventory is being questioned.
	 * @param clientUser The same user as serverUser, except safe for
	 *            the client to use.
	 */
	private static void getActivePageBackground (
			final AbstractUser serverUser, final UserProfile clientUser) {
		clientUser.setPageResource (Translator.getActiveItem (
				serverUser, clientUser, InventoryItemType
						.get ("tb-page-bg"), "pageBG"));
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getActiveTitleBackground we must retrieve the active item from
	 * the serverUser. If there is no active item for that user, use the
	 * default instead.
	 * 
	 * @param serverUser The user who's inventory is being questioned.
	 * @param clientUser The same user as serverUser, except safe for
	 *            the client to use.
	 */
	private static void getActiveTitleBackground (
			final AbstractUser serverUser, final UserProfile clientUser) {
		clientUser.setTitleResource (Translator.getActiveItem (
				serverUser, clientUser, InventoryItemType
						.get ("tb-title-bg"), "titleBG"));
	}

	/**
	 * <pre>
	 * twheys@gmail.com Jan 18, 2010
	 * </pre>
	 * 
	 * TO getAvailableItemsFromUser WRITEME...
	 * 
	 * @param serverUser WRITEME twheys@gmail.com
	 * @return AvailableItems object with data for displaying the
	 *         settings page.
	 */
	public static AvailableItems getAvailableItemsFromUser (
			final AbstractUser serverUser) {
		final AvailableItems availableItemsForUser = new AvailableItems ();
		Translator.logger
				.fine ("Retrieving inventory for ShadowUser ID#"
						+ serverUser.getUserID ());
		final Inventory inventory = serverUser.getInventory ();
		final Collection <InventoryItem> avatarBackgrounds = inventory
				.getItemsByType (InventoryItemType.get ("tb-avatar-bg"));
		Translator.logger.fine ("Number of avatar backgrounds: "
				+ avatarBackgrounds.size ());
		final Collection <InventoryItem> boxStyles = inventory
				.getItemsByType (InventoryItemType
						.get ("tb-box-styles"));
		Translator.logger.fine ("Number of box styles: "
				+ boxStyles.size ());
		final Collection <InventoryItem> icons = inventory
				.getItemsByType (InventoryItemType.get ("tb-icon"));
		Translator.logger.fine ("Number of icons: " + icons.size ());
		final Collection <InventoryItem> pageBackgrounds = inventory
				.getItemsByType (InventoryItemType.get ("tb-page-bg"));
		Translator.logger.fine ("Number of page backgrounds: "
				+ pageBackgrounds.size ());
		final Collection <InventoryItem> titleBackgrounds = inventory
				.getItemsByType (InventoryItemType.get ("tb-title-bg"));
		Translator.logger.fine ("Number of title backgrounds: "
				+ titleBackgrounds.size ());
		Translator.translateDataFromItems (availableItemsForUser,
				avatarBackgrounds, ThemeItemType.avatarBG);
		Translator.translateDataFromItems (availableItemsForUser,
				boxStyles, ThemeItemType.boxStyle);
		Translator.translateDataFromItems (availableItemsForUser,
				icons, ThemeItemType.icon);
		Translator.translateDataFromItems (availableItemsForUser,
				pageBackgrounds, ThemeItemType.pageBG);
		Translator.translateDataFromItems (availableItemsForUser,
				titleBackgrounds, ThemeItemType.titleBG);
		return availableItemsForUser;
	}

	/**
	 * <pre>
	 * twheys@gmail.com Dec 17, 2009
	 * </pre>
	 * 
	 * TO getBuddyList WRITEME...
	 * 
	 * @param serverUser WRITEME
	 * @return the client safe buddy list
	 */
	private static ShadowUser [] getBuddyList (
			final GeneralUser serverUser) {
		Collection <String> buddyListUnordered = serverUser
				.getBuddyListNames ();
		List <String> buddyList = new LinkedList <String> (
				buddyListUnordered);
		Collections.shuffle (buddyList);
		Translator.logger.info ("Populating "
				+ " buddies for ShadowUser ID#"
				+ serverUser.getUserID ());
		final List <ShadowUser> convertBuddyList = Translator
				.convertBuddyList (buddyList);
		return convertBuddyList
				.toArray (new ShadowUser [convertBuddyList.size ()]);
	}

	/**
	 * <pre>
	 * twheys@gmail.com Jan 18, 2010
	 * </pre>
	 * 
	 * TO getClientUser WRITEME...
	 * 
	 * @param serverUser WRITEME twheys@gmail.com
	 * @return the client safe ShadowUser
	 */
	private static UserProfile getClientUser (
			final AbstractUser serverUser) {
		final UserProfile clientUser = new UserProfile ();
		if (serverUser instanceof Toot) {
			clientUser.setBasicEight ( ((Toot) serverUser)
					.getBasic8Choice ());
			clientUser.setPeanuts ( ((Toot) serverUser).getPeanuts ()
					.intValue ());
		}
		clientUser.setUserID (serverUser.getUserID ());
		clientUser.setUserName (serverUser.getAvatarLabel ());
		if (serverUser instanceof org.starhope.appius.user.User) {
			clientUser
					.setBuddies (Translator
							.getBuddyList ((GeneralUser) serverUser));
		}
		clientUser.setPaid (serverUser.isPaidMember ());
		clientUser
				.setStatus (Translator.getTootBookStatus (serverUser));
		clientUser.setStaffLevel (serverUser.getStaffLevel ());
		return clientUser;
	}

	/**
	 * <pre>
	 * twheys@gmail.com Jan 18, 2010
	 * </pre>
	 * 
	 * TO getCommentFromReply WRITEME...
	 * 
	 * @param parentPost WRITEME twheys@gmail.com
	 * @param serverComment WRITEME twheys@gmail.com
	 * @return the client safe comment
	 */
	public static Post getCommentFromReply (final Post parentPost,
			final GameWorldMessage serverComment) {
		final Post clientComment = Translator
				.getPostFromPost (serverComment);
		clientComment.setParent (parentPost);
		clientComment.setParentID (parentPost.getId ());
		return clientComment;
	}

	/**
	 * WRITEME brpocock@star-hope.org Jul 30, 2010
	 * 
	 * @param userID WRITEME
	 * @return WRITEME
	 */
	private static String getIconForUser (final int userID) {
		Inventory inv;
		try {
			inv = Nomenclator.getDataRecord (Inventory.class, userID);
		} catch (final NotFoundException e1) {
			throw AppiusClaudiusCaecus.fatalBug (
					"can't load inventory for user #" + userID, e1);
		}
		int defaultIcon;
		try {
			defaultIcon = AppiusConfig
					.getInt ("com.tootsville.tootsbook.defaults.icon");
		} catch (final NumberFormatException e1) {
			throw AppiusClaudiusCaecus.fatalBug (
					"need default icon to be set as a number", e1);
		} catch (final NotFoundException e1) {
			throw AppiusClaudiusCaecus.fatalBug (
					"need default icon to be specified", e1);
		}
		inv.addDefaultFreeItem (defaultIcon);
		String iconName = String.valueOf (defaultIcon);
		try {
			iconName = String.valueOf (inv.getActiveItemByType (
					InventoryItemType.get ("tb-icon")).getGenericItem ()
					.getItemID ());
		} catch (final NotFoundException e) {
			iconName = String.valueOf (defaultIcon);
		} catch (final RuntimeException e) {
			// do nothing, use default
		}
		return iconName;
	}

	/**
	 * <pre>
	 * twheys@gmail.com Jan 18, 2010
	 * </pre>
	 * 
	 * TO getPostFromPost WRITEME...
	 * 
	 * @param serverPost WRITEME twheys@gmail.com
	 * @return the client safe Post
	 */
	public static Post getPostFromPost (
			final GameWorldMessage serverPost) {
		final Post clientPost = new Post ();
		clientPost.setId (serverPost.getID ());
		final String userNameForID = Nomenclator
				.getLoginForID (serverPost.getFromID ());
		final ShadowUser author = new ShadowUser (serverPost
				.getFromID (), userNameForID);
		final String iconName = Translator.getIconForUser (serverPost
				.getFromID ());
		author.setIcon (iconName);
		clientPost.setAuthor (author);
		clientPost.setMessage (serverPost.getBody ());
		clientPost.setTimeStamp (serverPost.getSent ().getTime ());
		clientPost.setAttachmentURL (serverPost.getAttachmentURL ());
		Translator.logger.finer ("Translated post: \n Author ID: "
				+ author.getUserID () + "\n Author Icon: " + iconName
				+ "\n Author Login: " + userNameForID + "\n Post ID: "
				+ clientPost.getId () + "\n Post Message: "
				+ clientPost.getMessage ());
		return clientPost;
	}

	/**
	 * WRITEME brpocock@star-hope.org Jul 30, 2010
	 * 
	 * @param serverUser WRITEME
	 * @return WRITEME
	 */
	private static String getTootBookStatus (
			final AbstractUser serverUser) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30, 2010)
		return "TootsBook Status Here";
	}

	/**
	 * @param serverUser WRITEME twheys@gmail.com
	 * @return javascript user bean
	 */
	public static UserProfile getUserFromUser (
			final AbstractUser serverUser) {
		final UserProfile clientUser = Translator
				.getClientUser (serverUser);
		Translator.getActiveAvatarBackground (serverUser, clientUser);
		Translator.getActiveBoxStyle (serverUser, clientUser);
		Translator.getActiveIcon (serverUser, clientUser);
		Translator.getActivePageBackground (serverUser, clientUser);
		Translator.getActiveTitleBackground (serverUser, clientUser);
		return clientUser;
	}

	/**
	 * WRITEME: Document this field. twheys@gmail.com Dec 16, 2009
	 * 
	 * @param data WRITEME twheys@gmail.com
	 * @param items WRITEME twheys@gmail.com
	 * @param type WRITEME twheys@gmail.com
	 */
	private static void translateDataFromItems (
			final AvailableItems data,
			final Collection <InventoryItem> items,
			final ThemeItemType type) {
		// Add active Item first
		for (final InventoryItem item : items) {
			if (item.isActive ()) {
				data.add (new ThemeItem (type, item.getID (), item
						.getGenericItem ().getTitle (), item.getGenericItem ()
						.getDescription (), item.getSlotNumber ()));
				Translator.logger.finest ("Adding Item ID: "
						+ item.getID () + "  Name: "
						+ item.getGenericItem ().getTitle ()
						+ "  Description: "
						+ item.getGenericItem ().getDescription ());
			}
		}

		// Add non active items second
		for (final InventoryItem item : items) {
			if ( !item.isActive ()) {
				data.add (new ThemeItem (type, item.getID (), item
						.getGenericItem ().getTitle (), item.getGenericItem ()
						.getDescription (), item.getSlotNumber ()));
				Translator.logger.finest ("Adding Item ID: "
						+ item.getID () + "  Name: "
						+ item.getGenericItem ().getTitle ()
						+ "  Description: "
						+ item.getGenericItem ().getDescription ());
			}
		}

	}
}
