package com.epson.iprint.storage.gdrivev3;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.Scope;
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;

public class IprintGoogleSignIn {

    public enum OperationType {
        DOWNLOAD,
        UPLOAD
    }

    public interface SignInListener {
        void onDisconnectCompleted();

        void onSignInComplete(boolean z, GoogleSignInAccount googleSignInAccount);
    }

    public interface StartActivityResultCallback {
        void onActivityResult(int i, Intent intent);
    }

    private static void handleLogin(Intent intent, final SignInListener signInListener) {
        GoogleSignIn.getSignedInAccountFromIntent(intent).addOnSuccessListener(new OnSuccessListener<GoogleSignInAccount>() {
            public void onSuccess(GoogleSignInAccount googleSignInAccount) {
                signInListener.onSignInComplete(true, googleSignInAccount);
            }
        }).addOnFailureListener(new OnFailureListener() {
            public void onFailure(@NonNull Exception exc) {
                signInListener.onSignInComplete(false, (GoogleSignInAccount) null);
            }
        });
    }

    public void startSignIn(@NonNull final SignInListener signInListener, @NonNull ActivityWrapper activityWrapper, @NonNull OperationType operationType) {
        if (getSignInAccount(activityWrapper.getActivity()) != null) {
            addTargetScope(activityWrapper, operationType);
        } else {
            activityWrapper.requestSignIn(getSignInIntent(activityWrapper.getActivity(), operationType), new StartActivityResultCallback() {
                public void onActivityResult(int i, Intent intent) {
                    if (i != -1) {
                        signInListener.onSignInComplete(false, (GoogleSignInAccount) null);
                    } else {
                        IprintGoogleSignIn.handleLogin(intent, signInListener);
                    }
                }
            });
        }
    }

    private void addTargetScope(@NonNull ActivityWrapper activityWrapper, @NonNull OperationType operationType) {
        Scope targetScope = getTargetScope(operationType);
        GoogleSignInAccount signInAccount = getSignInAccount(activityWrapper.getActivity());
        GoogleSignIn.requestPermissions(activityWrapper.getActivity(), activityWrapper.getSingInAddScopeRequestCode(), signInAccount, targetScope);
    }

    @NonNull
    private static Intent getSignInIntent(Activity activity, OperationType operationType) {
        return getGoogleSignInClient(activity, operationType).getSignInIntent();
    }

    @NonNull
    private static GoogleSignInClient getGoogleSignInClient(@NonNull Activity activity, OperationType operationType) {
        return GoogleSignIn.getClient(activity, new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().requestScopes(getTargetScope(operationType), new Scope[0]).build());
    }

    @NonNull
    private static Scope getTargetScope(OperationType operationType) {
        if (operationType == OperationType.DOWNLOAD) {
            return new Scope(GoogleDownloader.getTargetScope());
        }
        return new Scope(DriveWriter.getWriteScope());
    }

    public void disconnectAccount(@NonNull ActivityWrapper activityWrapper, @NonNull final SignInListener signInListener) {
        getGoogleSignInClient(activityWrapper.getActivity(), OperationType.DOWNLOAD).revokeAccess().addOnCompleteListener(activityWrapper.getActivity(), new OnCompleteListener<Void>() {
            public void onComplete(@NonNull Task<Void> task) {
                signInListener.onDisconnectCompleted();
            }
        });
    }

    public boolean isSignInValid(@NonNull Context context, OperationType operationType) {
        GoogleSignInAccount signInAccount = getSignInAccount(context);
        if (signInAccount == null) {
            return false;
        }
        return signInAccount.getGrantedScopes().contains(getTargetScope(operationType));
    }

    @Nullable
    public GoogleSignInAccount getSignInAccount(@NonNull Context context) {
        return GoogleSignIn.getLastSignedInAccount(context);
    }
}
