package org.arkiwi.app.rss;

import java.io.ByteArrayInputStream;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.arkiwi.app.feed.FeedItem;
import org.arkiwi.app.feed.FeedItemFile;
import org.arkiwi.app.feed.FeedQuery;
import org.arkiwi.app.interfaces.Define;
import org.arkiwi.app.interfaces.RssInterface;
import org.arkiwi.app.utility.SMethod;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class RssReader implements RssInterface, Define {
	@SuppressWarnings("unused")
	private final static String LOG_TAG = "RSSReader";
	private final static String m_ns = "media:";
	private final static String d_ns ="dc:";
	public static final int 
		STATE_INIT_VIEWER = -1,
		STATE_RESUME_VIEWER = 1,
		STATE_BACK_VIEWER = 2;
	
	private static int from_state = STATE_INIT_VIEWER;
	
	public static void setFromState(int state){
		from_state = state;
	}
	
	public static int getFromState(){
		return from_state;
	}
	
	private static RssReader instance = null;
	private static FeedQuery fq;

	private RssReader() {
		fq = new FeedQuery();
	}

	public static RssReader getInstance() {
		if (instance == null) {
			instance = new RssReader();
		} 
		
		return instance;
	}

	private String xmlEnclosureTypeAttr(Element item){
		String type = "dir";
		NodeList nodes = item.getElementsByTagName("enclosure");
		if (nodes.getLength() == 1){
			Element e = (Element) nodes.item(0);
			type = e.getAttributeNode("type").getValue();
		}
		
		return type;
	}
	
	private void xmlTitle(FeedItem fi, Element item){
		String title = getElementValue(item, "title");
		fi.setTitle(title);
	}
	
	private void xmlDescription(FeedItem fi, Element item){
		fi.setDescriprion(getElementValue(item, "description"));
	}
	
	private String xmlLink(Element item){
		return getElementValue(item, "link");
	}
	
	private void xmlPubDate(FeedItem fi, Element item){
		fi.setPubDate(getElementValue(item, "pubDate"));
	}
	
	private String xmlGuid(Element item){
		return getElementValue(item, "guid");
	}
	
	private void xmlCreator(FeedItem fi, Element item){
		((FeedItemFile) fi).setCreator(getElementValue(item,d_ns + "creator"));
	}
	//title //description //creator //subject //date //duration //coverage //hsize //publisher //album //year //tracknumber
	private void xmlKeywords(FeedItem fi, Element item){
		String keys = getElementValue(item,m_ns + "keywords");
		if (! keys.equalsIgnoreCase(""))
			((FeedItemFile) fi).setTags(keys);
	}
	
	private void xmlLicence(FeedItem fi, Element item){
		String license_url = "n.p.";
		
		NodeList nl = item.getElementsByTagName(m_ns + "license");
		if (nl.getLength()==1) {
			Element e = (Element) nl.item(0);
			license_url = e.getAttributeNode("href").getValue();
		}
		
		((FeedItemFile) fi).setLicense(license_url);
		//Log.d(LOG_TAG, "licence:" + license_url);
	}
	
	private Element xmlMediaContent(FeedItem fi, Element item){
		Element mContent = (Element) item.getElementsByTagName(m_ns + "content").item(0);
		
		((FeedItemFile) fi).setDownload(mContent.getAttributeNode("url").getValue());
		((FeedItemFile) fi).setSize(mContent.getAttributeNode("fileSize").getValue());
		((FeedItemFile) fi).setRate(mContent.getAttributeNode("samplingrate").getValue());
		((FeedItemFile) fi).setChannels(mContent.getAttributeNode("channels").getValue());
		((FeedItemFile) fi).setDuration(mContent.getAttributeNode("duration").getValue());
		
		return mContent;
	}
	
	private String getArkiwiView(String s, String add){
		String toRemove = "/html";
		int end = s.length() - toRemove.length();
		String ret = s.substring(0, end) + "/" + add;
		//Log.d(LOG_TAG, add + ":" + ret);
		return ret;
	}
	
	private boolean isFile(FeedItem fi){ 
		boolean isFile = true;
		if (fi.getMediaType().equalsIgnoreCase("dir"))
			isFile=false;
		
		return isFile;
	}
	
	private int xmlChannel(FeedQuery fq, Element channel) {
		int n=-1;
		
		fq.setTitle(getElementValue(channel, "title"));
		fq.setLink(getElementValue(channel, "link"));
		fq.setDesc(getElementValue(channel, "description"));
		
		Date refresh = new Date();
		String pubDate = getElementValue(channel, "pubDate");
		Date last = SMethod.stringToDate(A_DATE_ITEM, pubDate);
		if (last == null){
			n=0;
		}
	    
	    if (n != 0){
	    	fq.setRefresh(refresh.toString());
	    	fq.setLast(last.toString());
	    	//Log.d(LOG_TAG, "pDate: "+pubDate+" last:" + last + " - "+ fq.getLast()+ " refresh:"+refresh+" - "+fq.getRefresh());
		    //Log.d(LOG_TAG, "last:" + last + " a:" + last.after(refresh) + " b:" + last.before(refresh));
			//Log.d(LOG_TAG, "refresh:" + refresh + " a:" + refresh.after(last) + " b:" + refresh.before(last));
	    	n = 1;
		}
	    
	    return n;
	}
	
	public int setFeedQuery(String toParse) {
		//Log.d(LOG_TAG, "setFeedQuery()" + toParse);
		int nNode = 0;
		
		try {
			
			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
										.newDocumentBuilder();
			
			Document doc = builder.parse(new ByteArrayInputStream(toParse.getBytes()));
			
			int res = xmlChannel(fq,(Element) doc.getElementsByTagName("channel").item(0));
			//Log.d(LOG_TAG,"setFeedQuery()\n" + toParse + "\nres:"+res);
			if (res == 1) {
				NodeList nodes = doc.getElementsByTagName("item");
				nNode = nodes.getLength();
				for (int i = 0; i < nNode; i++) {
					Element item = (Element) nodes.item(i);
					String type = xmlEnclosureTypeAttr(item);
					String guid = xmlGuid(item);
					FeedItem fi = fq.addFeed(guid, type);
					fi.setMediaType(type);
					xmlTitle(fi, item);
					xmlDescription(fi, item);
					xmlPubDate(fi, item);
					
					String link = xmlLink(item);
					fi.setLink(getArkiwiView(link, "rss"));
					fi.setQrcode(getArkiwiView(link, "qrcode"));
					if (isFile(fi)) {
						xmlCreator(fi, item);
						Element mContent = xmlMediaContent(fi, item);
						xmlLicence(fi, mContent);
						xmlKeywords(fi, mContent);
						((FeedItemFile) fi).setTorrent(getArkiwiView(link, "torrent"));
					}
					//LogUtil.logFeed(LOG_TAG,fq);
				}
			} else if(res != 0) {
				nNode = XML_PAGLIAIO_DOWN;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		return nNode; 
	}
	
	public void setFeedQuery(FeedQuery q){
		fq = q;	
	}
	
	public void clearFeedQuery(){
		if (fq != null)
			fq.clear();
	}
	
	public FeedQuery getFeedQuery(){
		return fq;
	}

 	private String getCharacterDataFromElement(Element e) {
		try {
			Node child = e.getFirstChild();
			if (child instanceof CharacterData) {
				CharacterData cd = (CharacterData) child;
				return cd.getData();
			}
		} catch (Exception ex) {

		}
		return "";
	}

	protected float getFloat(String value) {
		if (value != null && !value.equals(""))
			return Float.parseFloat(value);
		else
			return 0;
	}

	protected String getElementValue(Element parent, String label) {
		return getCharacterDataFromElement((Element) parent
				.getElementsByTagName(label).item(0));
	}
}