/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * 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 androidx.car.app.sample.showcase.common.templates;

import static androidx.car.app.CarToast.LENGTH_LONG;

import android.graphics.Color;
import android.net.Uri;

import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.car.app.CarContext;
import androidx.car.app.CarToast;
import androidx.car.app.Screen;
import androidx.car.app.model.Action;
import androidx.car.app.model.CarColor;
import androidx.car.app.model.CarIcon;
import androidx.car.app.model.InputCallback;
import androidx.car.app.model.MessageTemplate;
import androidx.car.app.model.ParkedOnlyOnClickListener;
import androidx.car.app.model.Template;
import androidx.car.app.model.signin.InputSignInMethod;
import androidx.car.app.model.signin.PinSignInMethod;
import androidx.car.app.model.signin.ProviderSignInMethod;
import androidx.car.app.model.signin.QRCodeSignInMethod;
import androidx.car.app.model.signin.SignInTemplate;
import androidx.car.app.sample.showcase.common.R;
import androidx.car.app.sample.showcase.common.common.Utils;
import androidx.car.app.versioning.CarAppApiLevels;
import androidx.core.graphics.drawable.IconCompat;

/** A screen that demonstrates the sign-in template. */
public class SignInTemplateDemoScreen extends Screen {
    private static final String EMAIL_REGEXP = "^(.+)@(.+)$";
    private static final String EXPECTED_PASSWORD = "password";
    private static final int MIN_USERNAME_LENGTH = 5;
    private final CharSequence mAdditionalText;
    private final Action mProviderSignInAction;
    private final Action mPinSignInAction;
    private final Action mQRCodeSignInAction;
    // package private to avoid synthetic accessor
    State mState = State.USERNAME;
    String mLastErrorMessage = ""; // last displayed error message
    String mErrorMessage = "";
    String mUsername = null;

    public SignInTemplateDemoScreen(@NonNull CarContext carContext) {
        super(carContext);

        // Handle back pressed events manually, as we use them to navigate between templates within
        // the same screen.
        OnBackPressedCallback callback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                mErrorMessage = "";
                if (mState == State.USERNAME || mState == State.SIGNED_IN) {
                    getScreenManager().pop();
                } else {
                    mState = State.USERNAME;
                    invalidate();
                }
            }
        };
        carContext.getOnBackPressedDispatcher().addCallback(this, callback);

        mAdditionalText = Utils.clickable(getCarContext().getString(R.string.additional_text), 18,
                16,
                () -> getScreenManager().push(new LongMessageTemplateDemoScreen(getCarContext())));

        mProviderSignInAction = new Action.Builder()
                .setTitle(getCarContext().getString(R.string.google_sign_in))
                .setOnClickListener(ParkedOnlyOnClickListener.create(() -> {
                    mState = State.PROVIDER;
                    invalidate();
                }))
                .build();

        mPinSignInAction = new Action.Builder()
                .setTitle(getCarContext().getString(R.string.use_pin))
                .setOnClickListener(ParkedOnlyOnClickListener.create(() -> {
                    mState = State.PIN;
                    invalidate();
                }))
                .build();

        mQRCodeSignInAction = new Action.Builder()
                .setTitle(getCarContext().getString(R.string.qr_code))
                .setOnClickListener(ParkedOnlyOnClickListener.create(() -> {
                    mState = State.QR_CODE;
                    invalidate();
                }))
                .build();
    }

    @NonNull
    @Override
    public Template onGetTemplate() {
        if (getCarContext().getCarAppApiLevel() < CarAppApiLevels.LEVEL_2) {
            return new MessageTemplate.Builder(
                    getCarContext().getString(R.string.sign_in_template_not_supported_text))
                    .setTitle(getCarContext().getString(
                            R.string.sign_in_template_not_supported_title))
                    .setHeaderAction(Action.BACK)
                    .build();
        }
        switch (mState) {
            case USERNAME:
                return getUsernameSignInTemplate();
            case PASSWORD:
                return getPasswordSignInTemplate();
            case PIN:
                return getPinSignInTemplate();
            case PROVIDER:
                return getProviderSignInTemplate();
            case QR_CODE:
                return getQRCodeSignInTemplate();
            case SIGNED_IN:
                return getSignInCompletedMessageTemplate();
        }
        throw new IllegalStateException("Invalid state: " + mState);
    }

    private Template getUsernameSignInTemplate() {
        InputCallback listener = new InputCallback() {
            @Override
            public void onInputSubmitted(@NonNull String text) {
                if (mState == State.USERNAME) {
                    mUsername = text;
                    submitUsername();
                }
            }

            @Override
            public void onInputTextChanged(@NonNull String text) {
                // This callback demonstrates how to use handle the text changed event.
                // In this case, we check that the user name doesn't exceed a certain length.
                if (mState == State.USERNAME) {
                    mUsername = text;
                    mErrorMessage = validateUsername();

                    // Invalidate the template (and hence possibly update the error message) only
                    // if clearing up the error string, or if the error is changing.
                    if (!mLastErrorMessage.isEmpty()
                            && (mErrorMessage.isEmpty()
                            || !mLastErrorMessage.equals(mErrorMessage))) {
                        invalidate();
                    }
                }
            }
        };

        InputSignInMethod.Builder builder = new InputSignInMethod.Builder(listener)
                .setHint(getCarContext().getString(R.string.email_hint))
                .setKeyboardType(InputSignInMethod.KEYBOARD_EMAIL);
        if (mErrorMessage != null) {
            builder.setErrorMessage(mErrorMessage);
            mLastErrorMessage = mErrorMessage;
        }
        if (mUsername != null) {
            builder.setDefaultValue(mUsername);
        }
        InputSignInMethod signInMethod = builder.build();

        return new SignInTemplate.Builder(signInMethod)
                .addAction(mProviderSignInAction)
                .addAction(getCarContext().getCarAppApiLevel() > CarAppApiLevels.LEVEL_3
                        ? mQRCodeSignInAction : mPinSignInAction)
                .setTitle(getCarContext().getString(R.string.sign_in_title))
                .setInstructions(getCarContext().getString(R.string.sign_in_instructions))
                .setHeaderAction(Action.BACK)
                .setAdditionalText(mAdditionalText)
                .build();
    }

    /**
     * Validates the currently entered user name and returns an error message string if invalid,
     * or an empty string otherwise.
     */
    String validateUsername() {
        if (mUsername == null || mUsername.length() < MIN_USERNAME_LENGTH) {
            return getCarContext().getString(R.string.invalid_length_error_msg,
                    Integer.toString(MIN_USERNAME_LENGTH));
        } else if (!mUsername.matches(EMAIL_REGEXP)) {
            return getCarContext().getString(R.string.invalid_email_error_msg);
        } else {
            return "";
        }
    }

    /**
     * Moves to the password screen if the user name currently entered is valid, or displays
     * an error message otherwise.
     */
    void submitUsername() {
        mErrorMessage = validateUsername();

        boolean isError = !mErrorMessage.isEmpty();
        if (!isError) {
            // If there's no error, go to the password screen.
            mState = State.PASSWORD;
        }

        // Invalidate the template so that we either display an error, or go to the password screen.
        invalidate();
    }

    private Template getPasswordSignInTemplate() {
        InputCallback callback = new InputCallback() {
            @Override
            public void onInputSubmitted(@NonNull String text) {
                // Mocked password validation
                if (!EXPECTED_PASSWORD.equals(text)) {
                    mErrorMessage = getCarContext().getString(R.string.invalid_password_error_msg);
                } else {
                    mErrorMessage = "";
                    mState = State.SIGNED_IN;
                }
                invalidate();
            }
        };
        InputSignInMethod.Builder builder = new InputSignInMethod.Builder(callback)
                .setHint(getCarContext().getString(R.string.password_hint))
                .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD);
        if (mErrorMessage != null) {
            builder.setErrorMessage(mErrorMessage);
        }
        InputSignInMethod signInMethod = builder.build();

        return new SignInTemplate.Builder(signInMethod)
                .addAction(mProviderSignInAction)
                .addAction(getCarContext().getCarAppApiLevel() > CarAppApiLevels.LEVEL_3
                        ? mQRCodeSignInAction : mPinSignInAction)
                .setTitle(getCarContext().getString(R.string.sign_in_title))
                .setInstructions(
                        getCarContext().getString(R.string.password_sign_in_instruction_prefix)
                                + ": " + mUsername)
                .setHeaderAction(Action.BACK)
                .setAdditionalText(mAdditionalText)
                .build();
    }

    private Template getPinSignInTemplate() {
        PinSignInMethod pinSignInMethod = new PinSignInMethod("123456789ABC");
        return new SignInTemplate.Builder(pinSignInMethod)
                .setTitle(getCarContext().getString(R.string.sign_in_title))
                .setInstructions(getCarContext().getString(R.string.pin_sign_in_instruction))
                .setHeaderAction(Action.BACK)
                .setAdditionalText(mAdditionalText)
                .build();
    }

    private Template getQRCodeSignInTemplate() {
        QRCodeSignInMethod qrCodeSignInMethod = new QRCodeSignInMethod(Uri.parse("https://www"
                + ".youtube.com/watch?v=dQw4w9WgXcQ"));
        return new SignInTemplate.Builder(qrCodeSignInMethod)
                .setTitle(getCarContext().getString(R.string.qr_code_sign_in_title))
                .setHeaderAction(Action.BACK)
                .setAdditionalText(mAdditionalText)
                .addAction(mPinSignInAction)
                .addAction(mProviderSignInAction)
                .build();
    }

    private Template getProviderSignInTemplate() {
        IconCompat providerIcon = IconCompat.createWithResource(getCarContext(),
                R.drawable.ic_googleg);
        CarColor noTint = CarColor.createCustom(Color.TRANSPARENT, Color.TRANSPARENT);

        ProviderSignInMethod providerSignInMethod = new ProviderSignInMethod(
                new Action.Builder()
                        .setTitle(Utils.colorize(
                                getCarContext().getString(R.string.sign_in_with_google_title),
                                CarColor.createCustom(Color.BLACK, Color.BLACK), 0, 19))
                        .setBackgroundColor(CarColor.createCustom(Color.WHITE, Color.WHITE))
                        .setIcon(new CarIcon.Builder(providerIcon)
                                .setTint(noTint)
                                .build())
                        .setOnClickListener(ParkedOnlyOnClickListener.create(
                                this::performSignInWithGoogleFlow)).build());

        return new SignInTemplate.Builder(providerSignInMethod)
                .setTitle(getCarContext().getString(R.string.sign_in_title))
                .setInstructions(getCarContext().getString(R.string.provider_sign_in_instruction))
                .setHeaderAction(Action.BACK)
                .setAdditionalText(mAdditionalText)
                .build();
    }

    private void performSignInWithGoogleFlow() {
        // This is here for demonstration purposes, if the APK is not signed with a signature
        // that has been registered for sign in with Google flow, the sign in will fail at runtime.

//        Bundle extras = new Bundle(1);
//        extras.putBinder(BINDER_KEY, new SignInWithGoogleActivity.OnSignInComplete() {
//            @Override
//            public void onSignInComplete(@Nullable GoogleSignInAccount account) {
//                if (account == null) {
//                    CarToast.makeText(getCarContext(), "Error signing in", LENGTH_LONG).show();
//                    return;
//                }
//
//                // Use the account
//                CarToast.makeText(getCarContext(),
//                        account.getGivenName() + " signed in", LENGTH_LONG).show();
//            }
//        });
//        getCarContext().startActivity(
//                new Intent()
//                        .setClass(getCarContext(), SignInWithGoogleActivity.class)
//                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
//                        .putExtras(extras));
        CarToast.makeText(getCarContext(),
                        getCarContext().getString(R.string.sign_in_with_google_toast_msg),
                        LENGTH_LONG)
                .show();
    }

    private MessageTemplate getSignInCompletedMessageTemplate() {
        return new MessageTemplate.Builder(
                getCarContext().getString(R.string.sign_in_complete_text))
                .setTitle(getCarContext().getString(R.string.sign_in_complete_title))
                .setHeaderAction(Action.BACK)
                .addAction(new Action.Builder()
                        .setTitle(getCarContext().getString(R.string.sign_out_action_title))
                        .setOnClickListener(() -> {
                            mState = State.USERNAME;
                            invalidate();
                        })
                        .build())
                .build();
    }

    private enum State {
        USERNAME,
        PASSWORD,
        PIN,
        PROVIDER,
        QR_CODE,
        SIGNED_IN,
    }

}
