// 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.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import com.cloud.bridge.util.JsonAccessor;

/**
 * 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.errortext") + " Error Code - " +
                                queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode"));

                        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;
            }
            errorMessage = errorMessage.concat(" Error Code - " + Integer.toString(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);
    }
}
