package simplecloud.storage.providers.nirvanix;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import libcloud.exceptions.InvalidCredsException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import base.Driver;
import base.connection.ConnectionUserAndKey;
import base.interfaces.IResponse;

/*
 * Manages a connection to the Nirvanix storage cloud.
 */
public class NirvanixConnection extends ConnectionUserAndKey {
	
	private String appKey;
	
	private String sessionToken;
	
	private static final boolean SECURE = true;

	/*
	 * Constructs the Nirvanix connection.
	 * 
	 * @param appKey is necessary to authenticate with the API
	 * @param accessId identifies the user connecting to Nirvanix
	 * @param accessKey is the user's secret key
	 * @param host defines Nirvanix's host server
	 * @param driver references the driver that owns this connection
	 */
	public NirvanixConnection(String appKey, String accessId, String accessKey,
			String host, Driver driver) {
		super(accessId, accessKey, SECURE, host, driver);
		this.appKey = appKey;
		this.sessionToken = null;
		refreshSessionToken();
	}
	
	/* 
	 * Returns the session token that authenticates calls to the Nirvanix API.
	 * If this token expires, a new token must be issued using
	 * refreshSessionToken().
	 * 
	 * @return String is the session token to authenticate API calls
	 */
	public String getSessionToken() {
		if (sessionToken == null) refreshSessionToken();
		return sessionToken;
	}
	
	/*
	 * Refreshes the session token.
	 */
	public void refreshSessionToken() {
		// Request authentication
		Map<String, String> params = new HashMap<String, String>();
		params.put("appKey", appKey);
		params.put("username", accessId);
		params.put("password", accessKey);
		IResponse response = request("GET", "/ws/Authentication/Login.ashx", null, params, null);
		
		// Parse response
		XPath xpath = XPathFactory.newInstance().newXPath();
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(response.getBodyStream());
			Element root = doc.getDocumentElement();
			String responseCode = xpath.evaluate("/Response/ResponseCode", root);
			if (responseCode.equals("0")) {
				sessionToken = xpath.evaluate("/Response/SessionToken", root);
			} else {
				String errorMessage = xpath.evaluate("/Response/ErrorMessage", root);
				throw new InvalidCredsException(responseCode + ": " + errorMessage);
			}
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
