package com.mobify.astro.plugins;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;

import com.mobify.astro.AstroActivity;
import com.mobify.astro.AstroException;
import com.mobify.astro.AstroPlugin;
import com.mobify.astro.PluginResolver;
import com.mobify.astro.messaging.EventRegistrar;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.messaging.annotations.RpcMethod;
import com.mobify.astro.security.CryptoManager;

public class SecureStorePlugin extends AstroPlugin {

    private CryptoManager cryptoManager;
    private SharedPreferences sharedPref;
    private SharedPreferences.Editor editor;

    private final static String TAG = SecureStorePlugin.class.getName();
    private final static String SECURE_STORE_FILE_KEY = "com.mobify.astro.SECURE_STORAGE";

    final static String KEY_ERROR = "Key cannot be null or empty string.";
    final static String VALUE_ERROR = "Value cannot be null.";
    final static String INIT_ERROR = "SecureStorePlugin cannot be initialized.";

    class SecureStorePluginException extends AstroException {
        SecureStorePluginException(String message) {
            super(TAG + ": " + message);
        }
    }

    public SecureStorePlugin(@NonNull AstroActivity activity, @NonNull PluginResolver pluginResolver,
                             @NonNull EventRegistrar eventRegistrar, @NonNull MessageSender messageSender) throws AstroException {
        super(activity, pluginResolver, eventRegistrar, messageSender);

        sharedPref = activity.getSharedPreferences(SECURE_STORE_FILE_KEY, Context.MODE_PRIVATE);
        editor = sharedPref.edit();

        try {
            cryptoManager = new CryptoManager(activity, new CryptoManager.CryptoManagerListener() {
                @Override
                public void onKeysDestroy() {
                    clear();
                }
            });
        } catch (Exception e) {
            // On some devices ex. Samsung S3 the AndroidKeystore can reach an unrecoverable state
            // https://code.google.com/p/android/issues/detail?id=177459
            throw new SecureStorePluginException(INIT_ERROR);
        }

    }

    @RpcMethod(methodName = "set", parameterNames = {"key", "value"})
    public void set(String key, String value) throws Exception {
        if (key == null || key.isEmpty() || value == null) {
            throw new SecureStorePluginException(KEY_ERROR + " " + VALUE_ERROR);
        }

        delete(key);
        editor.putString(key, cryptoManager.encrypt(key, value));
        editor.apply();
    }

    @RpcMethod(methodName = "get", parameterNames = {"key"})
    public String get(String key) throws Exception {
        if (key == null || key.isEmpty()) {
            throw new SecureStorePluginException(KEY_ERROR);
        }

        String encryptedValue = sharedPref.getString(key, null);
        if (encryptedValue != null) {
            return cryptoManager.decrypt(key, encryptedValue);
        }
        return null;
    }

    @RpcMethod(methodName = "delete", parameterNames = {"key"})
    public void delete(String key) throws Exception {
        if (key == null || key.isEmpty()) {
            throw new SecureStorePluginException(KEY_ERROR);
        }

        editor.remove(key);
        editor.apply();
    }

    @RpcMethod(methodName = "clear")
    public void clear() {
        editor.clear();
        editor.apply();
    }
}
