/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed 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.firebase.ui.auth.ui.idp;

import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.util.Log;

import com.firebase.ui.auth.ErrorCodes;
import com.firebase.ui.auth.IdpResponse;
import com.firebase.ui.auth.ResultCodes;
import com.firebase.ui.auth.provider.AuthCredentialHelper;
import com.firebase.ui.auth.ui.BaseHelper;
import com.firebase.ui.auth.ui.TaskFailureLogger;
import com.firebase.ui.auth.ui.User;
import com.firebase.ui.auth.ui.accountlink.AccountLinker;
import com.firebase.ui.auth.ui.accountlink.WelcomeBackIdpPrompt;
import com.firebase.ui.auth.ui.accountlink.WelcomeBackPasswordPrompt;
import com.firebase.ui.auth.util.signincontainer.SaveSmartLock;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.ProviderQueryResult;
import com.google.firebase.auth.TwitterAuthProvider;

import java.util.List;

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class CredentialSignInHandler implements OnCompleteListener<AuthResult> {
    private static final String TAG = "CredentialSignInHandler";

    private Activity mActivity;
    private BaseHelper mHelper;
    @Nullable
    private SaveSmartLock mSmartLock;
    private IdpResponse mResponse;
    private int mAccountLinkRequestCode;

    public CredentialSignInHandler(
            Activity activity,
            BaseHelper helper,
            @Nullable SaveSmartLock smartLock,
            int accountLinkRequestCode,
            IdpResponse response) {
        mActivity = activity;
        mHelper = helper;
        mSmartLock = smartLock;
        mResponse = response;
        mAccountLinkRequestCode = accountLinkRequestCode;
    }

    @Override
    public void onComplete(@NonNull Task<AuthResult> task) {
        if (task.isSuccessful()) {
            FirebaseUser firebaseUser = task.getResult().getUser();
            mHelper.saveCredentialsOrFinish(
                    mSmartLock,
                    mActivity,
                    firebaseUser,
                    null,
                    mResponse);
        } else {
            if (task.getException() instanceof FirebaseAuthUserCollisionException) {
                String email = mResponse.getEmail();
                if (email != null) {
                    mHelper.getFirebaseAuth()
                            .fetchProvidersForEmail(email)
                            .addOnFailureListener(new TaskFailureLogger(
                                    TAG, "Error fetching providers for email"))
                            .addOnSuccessListener(new StartWelcomeBackFlow())
                            .addOnFailureListener(new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception e) {
                                    mHelper.finishActivity(
                                            mActivity,
                                            ResultCodes.CANCELED,
                                            IdpResponse.getErrorCodeIntent(ErrorCodes.UNKNOWN_ERROR));
                                }
                            });
                    return;
                }
            }
            Log.e(TAG,
                  "Unexpected exception when signing in with credential "
                          + mResponse.getProviderType()
                          + " unsuccessful. Visit https://console.firebase.google.com to enable it.",
                  task.getException());
            mHelper.dismissDialog();
        }
    }

    private class StartWelcomeBackFlow implements OnSuccessListener<ProviderQueryResult> {
        @Override
        public void onSuccess(@NonNull ProviderQueryResult result) {
            AuthCredential credential = AuthCredentialHelper.getAuthCredential(mResponse);
            if (mHelper.canLinkAccounts()
                    && credential != null
                    && result.getProviders().contains(credential.getProvider())) {
                // We don't want to show the welcome back dialog since the user selected
                // an existing account and we can just link the two accounts without knowing
                // prevCredential.
                AccountLinker.linkWithCurrentUser(mActivity, mHelper, mResponse, credential);
                return;
            }

            mHelper.dismissDialog();

            String provider = getHighestPriorityProvider(result.getProviders());
            if (provider.equals(EmailAuthProvider.PROVIDER_ID)) {
                // Start email welcome back flow
                mActivity.startActivityForResult(
                        WelcomeBackPasswordPrompt.createIntent(
                                mActivity,
                                mHelper.getFlowParams(),
                                mResponse
                        ), mAccountLinkRequestCode);
            } else {
                // Start Idp welcome back flow
                mActivity.startActivityForResult(
                        WelcomeBackIdpPrompt.createIntent(
                                mActivity,
                                mHelper.getFlowParams(),
                                new User.Builder(mResponse.getEmail())
                                        .setProvider(provider)
                                        .build(),
                                mResponse
                        ), mAccountLinkRequestCode);
            }
        }

        private String getHighestPriorityProvider(List<String> providers) {
            String googleProvider = null;
            String facebookProvider = null;
            String twitterProvider = null;
            String otherProvider = null;

            for (String provider : providers) {
                if (provider.equalsIgnoreCase(GoogleAuthProvider.PROVIDER_ID)) {
                    googleProvider = provider;
                } else if (provider.equalsIgnoreCase(FacebookAuthProvider.PROVIDER_ID)) {
                    facebookProvider = provider;
                } else if (provider.equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)) {
                    twitterProvider = provider;
                } else {
                    otherProvider = provider;
                }
            }

            if (googleProvider != null) return googleProvider;
            if (facebookProvider != null) return facebookProvider;
            if (twitterProvider != null) return twitterProvider;
            return otherProvider;
        }
    }
}

@@ -858,100 +858,19 @@
 uth.
-ErrorCodes;%0Aimport com.firebase.ui.auth.IdpResponse;%0Aimport com.firebase.ui.auth.ResultCodes
+IdpResponse
 ;%0Aim
@@ -3945,255 +3945,213 @@
     
-mHelper.finishActivity(%0A                                            mActivity,%0A                                            ResultCodes.CANCELED,%0A                                            IdpResponse.getErrorCodeIntent(ErrorCodes.UNKNOWN_ERROR));
+// TODO: What to do when signing in with Credential fails%0A                                    // and we can't continue to Welcome back flow without%0A                                    // knowing providers?
 %0A   

Remove unrelated changes