// 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
// 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.api;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.cloudstack.api.response.SuccessResponse;

import com.cloud.utils.exception.CloudRuntimeException;
import com.google.gson.Gson;

/**
 * Base class for API Test
 *
 */
public abstract class APITest {

    protected String rootUrl = "http://localhost:8080/client/api";
    protected String sessionKey = null;
    protected String cookieToSent = null;


    /**
     * Sending an api request through Http GET
     * @param command command name
     * @param params command query parameters in a HashMap
     * @return http request response string
     */
    protected String sendRequest(String command, HashMap<String, String> params){
        try {
            // Construct query string
            StringBuilder sBuilder = new StringBuilder();
            sBuilder.append("command=");
            sBuilder.append(command);
            if ( params != null && params.size() > 0){
                Iterator<String> keys = params.keySet().iterator();
                while (keys.hasNext()){
                    String key = keys.next();
                    sBuilder.append("&");
                    sBuilder.append(key);
                    sBuilder.append("=");
                    sBuilder.append(URLEncoder.encode(params.get(key), "UTF-8"));
                }
            }

            // Construct request url
            String reqUrl = rootUrl + "?" + sBuilder.toString();

            // Send Http GET request
            URL url = new URL(reqUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");

            if ( !command.equals("login") && cookieToSent != null){
                // add the cookie to a request
                conn.setRequestProperty("Cookie", cookieToSent);
            }
            conn.connect();


            if ( command.equals("login")){
                // if it is login call, store cookie
                String headerName=null;
                for (int i=1; (headerName = conn.getHeaderFieldKey(i))!=null; i++) {
                    if (headerName.equals("Set-Cookie")) {
                        String cookie = conn.getHeaderField(i);
                        cookie = cookie.substring(0, cookie.indexOf(";"));
                        String cookieName = cookie.substring(0, cookie.indexOf("="));
                        String cookieValue = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
                        cookieToSent = cookieName + "=" + cookieValue;
                    }
                }
            }

            // Get the response
            StringBuilder response = new StringBuilder();
            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            try {
                while ((line = rd.readLine()) != null) {
                    response.append(line);
                }
            } catch (EOFException ex) {
                // ignore this exception
                System.out.println("EOF exception due to java bug");
            }
            rd.close();



            return response.toString();

        } catch (Exception e) {
            throw new CloudRuntimeException("Problem with sending api request", e);
        }
    }

    protected String createMD5String(String password) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }


    protected Object fromSerializedString(String result, Class<?> repCls) {
        try {
            if (result != null && !result.isEmpty()) {
                // get real content
                int start;
                int end;
                if (repCls == LoginResponse.class || repCls == SuccessResponse.class) {

                    start = result.indexOf('{', result.indexOf('{') + 1); // find
                                                                          // the
                                                                          // second
                                                                          // {

                    end = result.lastIndexOf('}', result.lastIndexOf('}') - 1); // find
                                                                                // the
                                                                                // second
                                                                                // }
                                                                                // backwards

                } else {
                    // get real content
                    start = result.indexOf('{', result.indexOf('{', result.indexOf('{') + 1) + 1); // find
                                                                                                   // the
                                                                                                   // third
                                                                                                   // {
                    end = result.lastIndexOf('}', result.lastIndexOf('}', result.lastIndexOf('}') - 1) - 1); // find
                                                                                                             // the
                                                                                                             // third
                                                                                                             // }
                                                                                                             // backwards
                }
                if (start < 0 || end < 0) {
                    throw new CloudRuntimeException("Response format is wrong: " + result);
                }
                String content = result.substring(start, end + 1);
                Gson gson = ApiGsonHelper.getBuilder().create();
                return gson.fromJson(content, repCls);
            }
            return null;
        } catch (RuntimeException e) {
            throw new CloudRuntimeException("Caught runtime exception when doing GSON deserialization on: " + result, e);
        }
    }

    /**
     * Login call
     * @param username user name
     * @param password password (plain password, we will do MD5 hash here for you)
     * @return login response string
     */
    protected void login(String username, String password)
    {
        //String md5Psw = createMD5String(password);
        // send login request
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("response", "json");
        params.put("username", username);
        params.put("password", password);
        String result = this.sendRequest("login", params);
        LoginResponse loginResp = (LoginResponse)fromSerializedString(result, LoginResponse.class);
        sessionKey = loginResp.getSessionkey();

    }
}
