package uwl.rss.portal;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import uwl.rss.provider.RssItemProvider;
import com.sap.netweaver.bc.uwl.config.ItemType;
import com.sap.netweaver.bc.uwl.Attachment;
import com.sap.netweaver.bc.uwl.IUWLService;
import com.sap.netweaver.bc.uwl.Item;
import com.sap.netweaver.bc.uwl.ItemCollection;
import com.sap.netweaver.bc.uwl.ItemKey;
import com.sap.netweaver.bc.uwl.PriorityEnum;
import com.sap.netweaver.bc.uwl.ProviderStatus;
import com.sap.netweaver.bc.uwl.StatusEnum;
import com.sap.netweaver.bc.uwl.UWLContext;
import com.sap.netweaver.bc.uwl.UWLException;
import com.sap.netweaver.bc.uwl.WorkLog;
import com.sap.netweaver.bc.uwl.config.Action;
import com.sap.netweaver.bc.uwl.connect.ConnectorException;
import com.sap.netweaver.bc.uwl.connect.ConnectorFilter;
import com.sap.netweaver.bc.uwl.connect.ConnectorResult;
import com.sap.netweaver.bc.uwl.connect.IActionHandler;
import com.sap.netweaver.bc.uwl.connect.IProviderConnector;
import com.sap.tc.logging.Category;
import com.sap.tc.logging.Location;
import com.sap.tc.logging.Severity;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;


/**
 * @author Sumit Gogia,SAP
 *
 */
public class UwlRssConnector implements IProviderConnector {
	
	private static final Location loc = Location.getLocation(UwlRssConnector.class);

	//Connector Id
	public static final String RSS_CONNECTOR = "RssConnector";
	
	//reference to the Rss Item Provider
	private RssItemProvider rssProvider = new RssItemProvider();
	
	/*
	 * Item Type for our RSS Items. The Item Type defines which tab in UWL
	 * UI displays our Rss Items (and a lot of other things). 
	 */
	public static final String RSS_ITEM_TYPE = "uwl.task.rss";
	public static final String RSS_COMPLETED_ITEM_TYPE = "uwl.completedtask.rss";
	public static final String RSS_DELETED_ITEM = "uwl.deleted.rss";
	
	private ActionHandler actionHandler = null;
	private IUWLService uwlService = null;
	
	public UwlRssConnector(IUWLService uwlService) {
		this.uwlService = uwlService;
		try {
			this.actionHandler = new ActionHandler(uwlService.getPushChannel(),this);
		}
		catch(UWLException ue) {
			Category.APPLICATIONS.logThrowable(Severity.FATAL,
												loc,
												(Object)"UwlRssConnector()",
												new Object[]{this},
												"Error getting Push Channel from UWL Service. Exception in UwlRssConnector constructor",
												ue);
		}
	}
	
	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getActionHandler(java.lang.String)
	 */
	public IActionHandler getActionHandler(String actionHandlerId) {
		if(Action.PROVIDER_ACTION_HANDLER.equals(actionHandlerId))
			return actionHandler;
		else
			return null;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getAllActionsForItem(com.sap.netweaver.bc.uwl.UWLContext, java.util.Map, com.sap.netweaver.bc.uwl.Item)
	 */
	public Map getAllActionsForItem(UWLContext ctx,
									Map currentActions,
									Item item)
									throws ConnectorException {
		return currentActions;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getAttachmentHeaders(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item)
	 */
	public Attachment[] getAttachmentHeaders(UWLContext context,
												Item item)
											throws ConnectorException {
		return Item.EMPTY_ATTACHMENTS;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getDescription(com.sap.netweaver.bc.uwl.Item, com.sap.netweaver.bc.uwl.UWLContext)
	 */
	public String getDescription(Item item,
								UWLContext context)
								throws ConnectorException{
		/*
		 * just returning the item's description once again.
		 */
		return item.getDescription();
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getId()
	 */
	public String getId() {
		return UwlRssConnector.RSS_CONNECTOR;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getItem(com.sap.netweaver.bc.uwl.UWLContext, java.lang.String, java.lang.String)
	 */
	public Item getItem(UWLContext ctx,
						String systemId,
						String externalId)
						throws ConnectorException {
		try {
			return uwlService.getPushChannel().getItemByKey(new ItemKey(ctx.getUserId(),UwlRssConnector.RSS_CONNECTOR,systemId,externalId));
		}
		catch(UWLException ue) {
			//TODO - log the exception.
			throw new ConnectorException(ue);
		}
	}
	

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getItems(com.sap.netweaver.bc.uwl.UWLContext, java.lang.String, com.sap.netweaver.bc.uwl.connect.ConnectorFilter, java.lang.String)
	 */
	public ConnectorResult getItems(UWLContext context,
								String itemType,
								ConnectorFilter connectorFilter,
								String system)
								throws ConnectorException {
		
		/*
		 * get all the rss feeds for the user
		 * convert them to UWL Items
		 * add them to the connectorresult and give it back to UWL.
		 */
		 
		ConnectorResult result = null;
		List items = null;
		if(ItemType.matchType(RSS_ITEM_TYPE,itemType)){
			Hashtable feeds = rssProvider.getRssFeeds(context.getUserId());
			items = mapFeedsToUwlItems(context, itemType, connectorFilter, system, feeds);
		}
		else if(ItemType.matchType(RSS_COMPLETED_ITEM_TYPE,itemType)){ 
			/*
			 * in this case we don't return any new or modified items!
			 * let uwl use items from its cache.
			*/
			items = new ArrayList();
		}
		
		ProviderStatus  status = new ProviderStatus(true,system, UwlRssConnector.RSS_CONNECTOR);
		result = ConnectorResult.createDeltaResult(new ItemCollection(items),status);
		return result;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#getLogData(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item)
	 */
	public WorkLog getLogData(UWLContext context,
							Item item)
							throws ConnectorException{
		return null;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#isActionValidForItem(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item, com.sap.netweaver.bc.uwl.config.Action)
	 */
	public boolean isActionValidForItem(UWLContext ctx,
										Item item,
										Action action){
		return true;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#isItemValid(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item)
	 */
	public boolean isItemValid(UWLContext ctx,
								Item item)
								throws ConnectorException {
		return true;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#isLogRetrievalSupported(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item)
	 */
	public boolean isLogRetrievalSupported(UWLContext context,
											Item item){
		return false;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#needsRemoteConnection(java.lang.String)
	 */
	public boolean needsRemoteConnection(String systemId) {
		return true;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#populateHollowItem(com.sap.netweaver.bc.uwl.UWLContext, com.sap.netweaver.bc.uwl.Item)
	 */
	public boolean populateHollowItem(UWLContext context,
										Item item)
										throws ConnectorException {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#supportsCacheClearance(java.lang.String)
	 */
	public boolean supportsCacheClearance(String system) {
		return true;
	}

	/* (non-Javadoc)
	 * @see com.sap.netweaver.bc.uwl.connect.IProviderConnector#supportsItemType(java.lang.String)
	 */
	public boolean supportsItemType(String itemType) {
		if(itemType != null) {
			if(ItemType.matchType(RSS_ITEM_TYPE, itemType) || 
				(ItemType.matchType(RSS_COMPLETED_ITEM_TYPE,itemType)) ) return true;
		}
		return false;
	}
	
	private List mapFeedsToUwlItems (UWLContext context,
									String itemType,
									ConnectorFilter qp,
									String system,
									Hashtable feeds) {
		ArrayList retItems = new ArrayList();
		if( (feeds == null) || (feeds.isEmpty()) ) return retItems;
		
		Enumeration keys = feeds.keys();
		while(keys.hasMoreElements()) {
			String key = (String)keys.nextElement();
			SyndFeed feed = (SyndFeed)feeds.get(key);
			List entries = feed.getEntries();
			for(int j=0; j<entries.size();j++) {
				SyndEntry entry = (SyndEntry)entries.get(j);
				/*
				 * If the item was previously fetched, then we need to keep
				 * some attributes from the cached item - e.g. status.
				 */
				StatusEnum itemStatus = null;
				try {
					ItemKey itemKey = new ItemKey(context.getUserId(),UwlRssConnector.RSS_CONNECTOR,system,entry.getUri());
					Item cachedItem = uwlService.getPushChannel().getItemByKey(itemKey);
					if(cachedItem != null) {
						itemStatus = cachedItem.getStatus();
						//no need to update completed items.
						if(StatusEnum.COMPLETED.equals(itemStatus)) continue;
					}
				}
				catch (UWLException ue) {
					Category.APPLICATIONS.logThrowable(Severity.FATAL,
														loc,
														(Object)"mapFeedsToUwlItems()",
														new Object[]{this},
														"Error fetching cached item from PushChannel",
														ue);
					
				}

				Item uwlItem = new Item(UwlRssConnector.RSS_CONNECTOR, 	//connectorId
										system,							//systemId
										entry.getUri(),					//externalId
										context.getUserId(),			//userId
										-1, 							//attachment count
										entry.getPublishedDate(),		//date created
										entry.getAuthor(),				//creator id
										null,							//due date
										null,							//external object id
										RSS_ITEM_TYPE,					//external type
										RSS_ITEM_TYPE,					//item type
										PriorityEnum.LOW,				//priority
										(itemStatus==null)?
										StatusEnum.NEW:itemStatus,		//status
										entry.getTitle() );				//subject
				
				
				
				if( (uwlItem.getCreatorId() == null) || (uwlItem.getCreatorId().equals("")) ) {
					String title = feed.getTitle();
					if( (title == null) || (title.equals("")) ) {
						uwlItem.setCreatorId(key);
					}
					else uwlItem.setCreatorId(title);
				}
				uwlItem.setDescription(entry.getDescription().getValue());
				uwlItem.setExecutionUrl(entry.getLink());
				retItems.add(uwlItem);
			}
		}
		return retItems;
	}
}
