import sixapi.*;

import java.util.Enumeration;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.BufferedReader;
import java.io.IOException;

public class SixResponse implements SixResponseListener {

	private boolean isLoggedIn = false;
	private Map<String, HashMap<Integer, String>> idToNameDictionary = new HashMap<String, HashMap<Integer, String>>();
	private Map<String, HashMap<String,Object>> cookieToNewsUpdate = new HashMap<String, HashMap<String, Object>>();
	private SixEventHandler eventHandler;
	private CookieHandler cookieHandler;
	private DBWrapper dbWrapper;
	
	public SixResponse(SixEventHandler evtH, CookieHandler ch, DBWrapper dbR)
	{
		eventHandler = evtH;
		cookieHandler = ch;
		dbWrapper = dbR;
	}
	
	public void setIsLoggedIn(boolean iLI)
	{
		isLoggedIn = iLI;
	}
	
	public boolean getIsLoggedIn()
	{
		return isLoggedIn;
	}

	public void processLoginResponse(SixLoginRes response) {
		System.out.println("processLoginResponse "+response);
		if(SixStatusCodes.OK==response.getStatus())
			isLoggedIn=true;
		else
			System.out.println("Trouble logging in");
	}

	public void processLogoutResponse(SixLogoutRes response) {
		System.out.println("processLogoutResponse "+response);
	}

	public void processCreateResponse(SixCreateRes response) {
		System.out.println("processCreateResponse "+response);
	}

	public void processPutResponse(SixPutRes response) {
		System.out.println("processPutResponse "+response);
	}

	public void processDeleteResponse(SixDeleteRes response) {
		System.out.println("processDeleteResponse "+response);
	}

	public void processUnsubscribeResponse(SixUnsubscribeRes response) {
		System.out.println("processUnsubscribeResponse "+response);
	}

	public void processGetFieldSetResponse(SixGetFieldSetRes response) {
		System.out.println("processFieldSetResponse "+response);
		
		String localCookie = cookieHandler.getCookie(response);
		
		if (localCookie == null)
			return;
		
		if (!idToNameDictionary.containsValue(localCookie)){
			idToNameDictionary.put(localCookie, new HashMap<Integer, String>());
		}
	
		if (response.getStatus() == SixStatusCodes.OK) {
			for (int i = 0; i < response.noOfRecords(); i++) {
				(idToNameDictionary.get(localCookie)).put(i,response.getName(i));
				dbWrapper.AddColumn(localCookie, response.getName(i));
				if (response.getFlags(i).get(SixGetFieldSetRes.FF_KEY))
				{
					dbWrapper.AddKey(localCookie, response.getName(i));
				}
			}
		}
	}

	public void processDataResponse(SixDataRes response) {		
		String[] cookie = response.getPropertyValue(SixCmd.COOKIE_PROP);

		if (cookie == null)
			return;
		
		String localCookie = Arrays.toString(cookie);
		
		if(response.isTextData()){	
			BufferedReader buf = response.getTextStream();
			String newsText = "";
			String in=null;
			try {
				while( (in = buf.readLine())!=null)
				{
					newsText = newsText + in + "\n";
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			String recordId = cookieToNewsUpdate.get(localCookie).get("recordId").toString();
			dbWrapper.UpdateNewsText(localCookie, recordId, newsText);
			
		}// End text data

		if( response.isTableData() ){		
			processTableData(response, localCookie);
		}
	}

	private void processTableData(SixDataRes response, String localCookie){
		SixTableData data = response.create();
		
		// This is a hack to handle the unchecked operation from the old API
		List <SixRecord>records = new ArrayList<SixRecord>();
		Enumeration<?> v = data.elements();
		while (v.hasMoreElements()){	
			SixRecord r = (SixRecord.class).cast(v.nextElement());
			records.add(r);
		}
		
		for (SixRecord rec: records)
		{			
			HashMap<String,Object> nameToValue = new HashMap<String,Object>();
			String id = Long.toString(rec.getId());
			nameToValue.put("recordId", id);
			boolean isNewsText = false;
			
			Enumeration values = rec.elements();
			while(values.hasMoreElements()){
				SixField field = (SixField)values.nextElement();
				
				if (field.getType() == SixField.FT_LINK)
				{
					isNewsText = true;
				}
				
				if (field.getData() != null)
				{
					nameToValue.put(idToNameDictionary.get(localCookie).get(field.getId()), field.getData());
				}
			}
			dbWrapper.Update(localCookie, id, dbWrapper.CreateKeyIfExist(localCookie, nameToValue), nameToValue);
			
			// This is a news update, lets fetch the text
			if (isNewsText)
			{
				createNewsTextQuery(nameToValue);
			}
		}
	}

	public void processErrorResponse(SixException error) 
	{
		System.out.println("processErrorResponse "+error);
	}
	
	private void createNewsTextQuery(HashMap<String,Object> nameToValue)
	{
		try
		{
			if (nameToValue.get("Text") != null)
			{
				// Link looks like this raw sixp:/rt/newsart?Id="urn:newsml:six.se:20140806:DJ_20140806005734:1";text
				String rawLink = nameToValue.get("Text").toString();
				// Should look like this /rt/newsart?Id="urn:newsml:six.se:20140806:DJ_20140806005734:1"
				String fixedLink = rawLink.replaceAll("sixp:","").replaceAll(";text","");
				SixId reqId = new SixId(fixedLink);
				SixGetReq getReq = new SixGetReq(reqId);
				getReq.setProperty(SixCmd.COOKIE_PROP, cookieHandler.getNextCookie());
				cookieToNewsUpdate.put(cookieHandler.addBrackets(cookieHandler.currentCookieString()), nameToValue);
				eventHandler.send(getReq);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}	
}