// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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
 * 
 */
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("CloudSatck API response doesn't contain responseObjName:" + responseObjName +
                                        " because response is empty");
				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);
	}
}
