package by.chemerisuk.cordova.firebase;

import android.util.Log;
import java.util.concurrent.TimeUnit;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GetTokenResult;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.FirebaseException;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


public class FirebaseAuthenticationPlugin extends CordovaPlugin {
    private static final String TAG = "FirebaseAuthentication";

    private FirebaseAuth firebaseAuth;

    @Override
    protected void pluginInitialize() {
        Log.d(TAG, "Starting Firebase Authentication plugin");

        this.firebaseAuth = FirebaseAuth.getInstance();
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("getIdToken")) {
            getIdToken(args.getBoolean(0), callbackContext);

            return true;
        } else if (action.equals("signInWithEmailAndPassword")) {
            signInWithEmailAndPassword(args.getString(0), args.getString(1), callbackContext);

            return true;
        } else if (action.equals("verifyPhoneNumber")) {
            verifyPhoneNumber(args.getString(0), args.getLong(1), callbackContext);

            return true;
        }

        return false;
    }

    private void getIdToken(final boolean forceRefresh, final CallbackContext callbackContext) throws JSONException {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                FirebaseUser user = firebaseAuth.getCurrentUser();

                if (user == null) {
                    callbackContext.error("User is not authorized");
                } else {
                    user.getIdToken(forceRefresh)
                        .addOnCompleteListener(cordova.getActivity(), new OnCompleteListener<GetTokenResult>() {
                            @Override
                            public void onComplete(Task<GetTokenResult> task) {
                                if (task.isSuccessful()) {
                                    callbackContext.success(task.getResult().getToken());
                                } else {
                                    callbackContext.error(task.getException().getMessage());
                                }
                            }
                        });
                }
            }
        });
    }

    private void signInWithEmailAndPassword(final String email, final String password, final CallbackContext callbackContext) throws JSONException {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                firebaseAuth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener(cordova.getActivity(), new OnCompleteListener<AuthResult>() {
                        @Override
                        public void onComplete(Task<AuthResult> task) {
                            if (task.isSuccessful()) {
                                FirebaseUser user = task.getResult().getUser();

                                callbackContext.success(getProfileData(user));
                            } else {
                                callbackContext.error(task.getException().getMessage());
                            }
                        }
                    });
            }
        });
    }

    private void verifyPhoneNumber(String phoneNumber, long timeout, final CallbackContext callbackContext) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber, timeout, TimeUnit.MILLISECONDS, this.cordova.getActivity(),
            new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                @Override
                public void onVerificationCompleted(PhoneAuthCredential credential) {
                    FirebaseUser user = firebaseAuth.getCurrentUser();
                    if (user != null) {
                        user.updatePhoneNumber(credential);
                    }
                }

                @Override
                public void onCodeAutoRetrievalTimeOut(String verificationId) {
                    callbackContext.error(verificationId);
                }

                @Override
                public void onVerificationFailed(FirebaseException exception) {
                    callbackContext.error(exception.getMessage());
                }
            }
        );
    }

    private JSONObject getProfileData(FirebaseUser user) {
        JSONObject result = new JSONObject();

        try {
            result.put("uid", user.getUid());
            result.put("displayName", user.getDisplayName());
            result.put("email", user.getEmail());
            result.put("phone", user.getPhoneNumber());
            result.put("photoURL", user.getPhotoUrl());
            result.put("providerId", user.getProviderId());
        } catch (JSONException e) {
            Log.e(TAG, "Fail to process getProfileData", e);
        }

        return result;
    }
}

@@ -4067,21 +4067,16 @@
 ECONDS, 
-this.
 cordova.
@@ -4380,9 +4380,9 @@
 ser 
-!
+=
 = nu
@@ -4415,41 +4415,1349 @@
     
-user.updatePhoneNumber(credential
+firebaseAuth.signInWithCredential(credential)%0A                            .addOnCompleteListener(cordova.getActivity(), new OnCompleteListener%3CAuthResult%3E() %7B%0A                                @Override%0A                                public void onComplete(Task%3CAuthResult%3E task) %7B%0A                                    if (task.isSuccessful()) %7B%0A                                        callbackContext.success();%0A                                    %7D else %7B%0A                                        callbackContext.error(task.getException().getMessage());%0A                                    %7D%0A                                %7D%0A                            %7D);%0A                    %7D else %7B%0A                        user.updatePhoneNumber(credential)%0A                            .addOnCompleteListener(cordova.getActivity(), new OnCompleteListener%3CVoid%3E() %7B%0A                                @Override%0A                                public void onComplete(Task%3CVoid%3E task) %7B%0A                                    if (task.isSuccessful()) %7B%0A                                        callbackContext.success();%0A                                    %7D else %7B%0A                                        callbackContext.error(task.getException().getMessage());%0A                                    %7D%0A                                %7D%0A                            %7D
 );%0A 
@@ -5938,21 +5938,23 @@
 Context.
-error
+success
 (verific
@@ -6076,24 +6076,16 @@
 eption e
-xception
 ) %7B%0A    
@@ -6123,24 +6123,16 @@
 .error(e
-xception
 .getMess

update verifyPhoneNumber