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

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

// To maintain independency of console proxy project, we duplicate this class from console proxy project
public class ConsoleProxyPasswordBasedEncryptor {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class);

    private Gson gson;

    // key/IV will be set in 128 bit strength
    private KeyIVPair keyIvPair;

    public ConsoleProxyPasswordBasedEncryptor(String password) {
        gson = new GsonBuilder().create();
        keyIvPair = gson.fromJson(password, KeyIVPair.class);
    }

    public String encryptText(String text) {
        if (text == null || text.isEmpty())
            return text;

        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES");

            cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes()));

            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
            return Base64.encodeBase64URLSafeString(encryptedBytes);
        } catch (NoSuchAlgorithmException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (NoSuchPaddingException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (IllegalBlockSizeException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (BadPaddingException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (InvalidKeyException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (InvalidAlgorithmParameterException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        }
    }

    public String decryptText(String encryptedText) {
        if (encryptedText == null || encryptedText.isEmpty())
            return encryptedText;

        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes()));

            byte[] encryptedBytes = Base64.decodeBase64(encryptedText);
            return new String(cipher.doFinal(encryptedBytes));
        } catch (NoSuchAlgorithmException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (NoSuchPaddingException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (IllegalBlockSizeException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (BadPaddingException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (InvalidKeyException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        } catch (InvalidAlgorithmParameterException e) {
            s_logger.error("Unexpected exception ", e);
            return null;
        }
    }

    public <T> String encryptObject(Class<?> clz, T obj) {
        if (obj == null)
            return null;

        String json = gson.toJson(obj);
        return encryptText(json);
    }

    @SuppressWarnings("unchecked")
    public <T> T decryptObject(Class<?> clz, String encrypted) {
        if (encrypted == null || encrypted.isEmpty())
            return null;

        String json = decryptText(encrypted);
        return (T)gson.fromJson(json, clz);
    }

    public static class KeyIVPair {
        String base64EncodedKeyBytes;
        String base64EncodedIvBytes;

        public KeyIVPair() {
        }

        public KeyIVPair(String base64EncodedKeyBytes, String base64EncodedIvBytes) {
            this.base64EncodedKeyBytes = base64EncodedKeyBytes;
            this.base64EncodedIvBytes = base64EncodedIvBytes;
        }

        public byte[] getKeyBytes() {
            return Base64.decodeBase64(base64EncodedKeyBytes);
        }

        public void setKeyBytes(byte[] keyBytes) {
            base64EncodedKeyBytes = Base64.encodeBase64URLSafeString(keyBytes);
        }

        public byte[] getIvBytes() {
            return Base64.decodeBase64(base64EncodedIvBytes);
        }

        public void setIvBytes(byte[] ivBytes) {
            base64EncodedIvBytes = Base64.encodeBase64URLSafeString(ivBytes);
        }
    }

}
