/*
 * Copyright (C) 2011 Citrix Systems, Inc.  All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.cloud.stack;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.bridge.util.JsonAccessor;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

/**
 * CloudStackClient implements a simple CloudStack client object, it can be used to execute CloudStack commands 
 * with JSON response
 * 
 * @author Kelven Yang
 */
public class CloudStackClient {
    protected final static Logger logger = Logger.getLogger(CloudStackClient.class);
    
	private String _serviceUrl;
	
	private long _pollIntervalMs = 2000;			// 1 second polling interval
	private long _pollTimeoutMs = 600000;			// 10 minutes polling timeout

	public CloudStackClient(String serviceRootUrl) {
		assert(serviceRootUrl != null);
		
		if(!serviceRootUrl.endsWith("/"))
			_serviceUrl = serviceRootUrl + "/api?";
		else
			_serviceUrl = serviceRootUrl + "api?";
	}
	
	public CloudStackClient(String cloudStackServiceHost, int port, boolean bSslEnabled) {
		StringBuffer sb = new StringBuffer();
		if(!bSslEnabled) {
			sb.append("http://" + cloudStackServiceHost);
			if(port != 80)
				sb.append(":").append(port);
		} else {
			sb.append("https://" + cloudStackServiceHost);
			if(port != 443)
				sb.append(":").append(port);
		}
		
		//
		// If the CloudStack root context path has been from /client to some other name
		// use the first constructor instead
		//
		sb.append("/client/api");
		sb.append("?");
		_serviceUrl = sb.toString();
	}
	
	public CloudStackClient setPollInterval(long intervalMs) {
		_pollIntervalMs = intervalMs;
		return this;
	}
	
	public CloudStackClient setPollTimeout(long pollTimeoutMs) {
		_pollTimeoutMs = pollTimeoutMs;
		return this;
	}
	
	public <T> T call(CloudStackCommand cmd, String apiKey, String secretKey, boolean followToAsyncResult, 
		String responseName, String responseObjName, Class<T> responseClz)	throws Exception {
		
		assert(responseName != null);
		
		JsonAccessor json = execute(cmd, apiKey, secretKey);
		if(followToAsyncResult && json.tryEval(responseName + ".jobid") != null) {
			long startMs = System.currentTimeMillis();
	        while(System.currentTimeMillis() -  startMs < _pollTimeoutMs) {
				CloudStackCommand queryJobCmd = new CloudStackCommand("queryAsyncJobResult");
	        	queryJobCmd.setParam("jobId", json.getAsString(responseName + ".jobid"));
	        	
	        	JsonAccessor queryAsyncJobResponse = execute(queryJobCmd, apiKey, secretKey);

	    		if(queryAsyncJobResponse.tryEval("queryasyncjobresultresponse") != null) {
	    			int jobStatus = queryAsyncJobResponse.getAsInt("queryasyncjobresultresponse.jobstatus");
	    			switch(jobStatus) {
	    			case 2:
	    	    		throw new Exception(queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") + " " + 
    	    				queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext"));
	    	    		
	    			case 0 :
	            	    try { 
	            	    	Thread.sleep( _pollIntervalMs ); 
	            	    } catch( Exception e ) {}
	            	    break;
	            	    
	    			case 1 :
	    				if(responseObjName != null)
	    					return (T)(new Gson()).fromJson(queryAsyncJobResponse.eval("queryasyncjobresultresponse.jobresult." + responseObjName), responseClz);
	    				else
	    					return (T)(new Gson()).fromJson(queryAsyncJobResponse.eval("queryasyncjobresultresponse.jobresult"), responseClz);
	    				
	    			default :
	    				assert(false);
	                    throw new Exception("Operation failed - invalid job status response");
	    			}
	    		} else {
	                throw new Exception("Operation failed - invalid JSON response");
	    		}
	        }
	        
            throw new Exception("Operation failed - async-job query timed out");
		} else {
			if (responseObjName != null)
				return (T)(new Gson()).fromJson(json.eval(responseName + "." + responseObjName), responseClz);
			else
				return (T)(new Gson()).fromJson(json.eval(responseName), responseClz);
		}
	}

	// collectionType example :  new TypeToken<List<String>>() {}.getType();
	public <T> List<T> listCall(CloudStackCommand cmd, String apiKey, String secretKey, 
		String responseName, String responseObjName, Type collectionType) throws Exception {
		
		assert(responseName != null);
		
		JsonAccessor json = execute(cmd, apiKey, secretKey);
		
		

		if(responseObjName != null)
			try {
				return (new Gson()).fromJson(json.eval(responseName + "." + responseObjName), collectionType);
			} catch(Exception e) {
				// this happens because responseObjName won't exist if there are no objects in the list.
				logger.debug("Unable to find responseObjName:[" + responseObjName + "].  Returning null! Exception: " + e.getMessage());
				return null;
			}
		return (new Gson()).fromJson(json.eval(responseName), collectionType);
	}

	public JsonAccessor execute(CloudStackCommand cmd, String apiKey, String secretKey) throws Exception {
		JsonParser parser = new JsonParser();
		URL url = new URL(_serviceUrl + cmd.signCommand(apiKey, secretKey));
		
		if(logger.isDebugEnabled())
			logger.debug("Cloud API call + [" + url.toString() + "]");
		
        URLConnection connect = url.openConnection();
        
        int statusCode;
        statusCode = ((HttpURLConnection)connect).getResponseCode();
        if(statusCode >= 400) {
        	logger.error("Cloud API call + [" + url.toString() + "] failed with status code: " + statusCode);
            String errorMessage = ((HttpURLConnection)connect).getResponseMessage();
            if(errorMessage == null){
                errorMessage = connect.getHeaderField("X-Description");
            }
            
            if(errorMessage == null){
                errorMessage = "CloudStack API call HTTP response error, HTTP status code: " + statusCode;
            }

        	throw new IOException(errorMessage);
        }
        
        InputStream inputStream = connect.getInputStream(); 
		JsonElement jsonElement = parser.parse(new InputStreamReader(inputStream));
		if(jsonElement == null) {
        	logger.error("Cloud API call + [" + url.toString() + "] failed: unable to parse expected JSON response");
        	
        	throw new IOException("CloudStack API call error : invalid JSON response");
		}
		
		if(logger.isDebugEnabled())
			logger.debug("Cloud API call + [" + url.toString() + "] returned: " + jsonElement.toString());
		return new JsonAccessor(jsonElement);
	}
}
