/*
 * Copyright (C) 2023 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 android.platform.helpers;

import android.app.Instrumentation;
import android.platform.helpers.ScrollUtility.ScrollActions;
import android.platform.helpers.ScrollUtility.ScrollDirection;

import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;

/** Implementation of {@link IAutoUserHelper} to support tests of account settings */
public class SettingUserHelperImpl extends AbstractStandardAppHelper implements IAutoUserHelper {
    // constants
    private static final String TAG = "SettingUserHelperImpl";
    private static final int MAX_WAIT_COUNT = 4;
    private static final int WAIT_MS = 40000;

    private static final int TEN_SECONDS_WAIT = 10000;

    private ScrollUtility mScrollUtility;
    private ScrollActions mScrollAction;
    private BySelector mBackwardButtonSelector;
    private BySelector mForwardButtonSelector;
    private BySelector mScrollableElementSelector;
    private ScrollDirection mScrollDirection;
    private UiObject2 mEnableOption;
    public SettingUserHelperImpl(Instrumentation instr) {
        super(instr);
        mScrollUtility = ScrollUtility.getInstance(getSpectatioUiUtil());
        mScrollAction =
                ScrollActions.valueOf(
                        getActionFromConfig(AutomotiveConfigConstants.USER_SETTINGS_SCROLL_ACTION));
        mBackwardButtonSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.USER_SETTINGS_SCROLL_BACKWARD);
        mForwardButtonSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.USER_SETTINGS_SCROLL_FORWARD);
        mScrollableElementSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.USER_SETTINGS_SCROLL_ELEMENT);
        mScrollDirection =
                ScrollDirection.valueOf(
                        getActionFromConfig(
                                AutomotiveConfigConstants.USER_SETTINGS_SCROLL_DIRECTION));
        mScrollUtility.setScrollValues(
                Integer.valueOf(
                        getActionFromConfig(AutomotiveConfigConstants.USER_SETTINGS_SCROLL_MARGIN)),
                Integer.valueOf(
                        getActionFromConfig(
                                AutomotiveConfigConstants.USER_SETTINGS_SCROLL_WAIT_TIME)));
    }
    /** {@inheritDoc} */
    @Override
    public String getPackage() {
        return getPackageFromConfig(AutomotiveConfigConstants.USER_SETTINGS_PACKAGE);
    }
    /** {@inheritDoc} */
    @Override
    public String getLauncherName() {
        throw new UnsupportedOperationException("Operation not supported.");
    }
    /** {@inheritDoc} */
    @Override
    public void dismissInitialDialogs() {
        // Nothing to dismiss
    }
    /** {@inheritDoc} */
    // Add a new user
    @Override
    public void addUser() {
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_ADD_PROFILE);
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_OK);
        skipSetupWizard();
        getSpectatioUiUtil()
                .waitForUiObject(
                        getUiElementFromConfig(AutomotiveConfigConstants.HOME_PROFILE_ICON_BUTTON),
                        WAIT_MS);
    }
    // opens permission page of a user
    @Override
    public void openPermissionsPage(String user) {
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MANAGE_OTHER_PROFILES);
        BySelector userSelector = By.text(user);
        UiObject2 userObject = getSpectatioUiUtil().findUiObject(userSelector);
        getSpectatioUiUtil().validateUiObject(userObject, String.format("User %s", user));
        getSpectatioUiUtil().clickAndWait(userObject);
        getSpectatioUiUtil()
                .waitForUiObject(
                        getUiElementFromConfig(
                                AutomotiveConfigConstants.USER_SETTINGS_TOGGLE_BUTTON),
                        WAIT_MS);
    }
    // delete an existing user
    @Override
    public void deleteUser(String user) {
        if (isUserPresent(user)) {
            BySelector userSelector = By.text(user);
            UiObject2 userObject = getSpectatioUiUtil().findUiObject(userSelector);
            getSpectatioUiUtil().validateUiObject(userObject, String.format("User %s", user));
            getSpectatioUiUtil().clickAndWait(userObject);
            clickbutton(AutomotiveConfigConstants.USER_SETTINGS_DELETE);
            clickbutton(AutomotiveConfigConstants.USER_SETTINGS_DELETE);
            getSpectatioUiUtil()
                    .waitForUiObject(
                            getUiElementFromConfig(
                                    AutomotiveConfigConstants.USER_SETTINGS_ADD_PROFILE),
                            TEN_SECONDS_WAIT);
        }
    }
    // delete self User
    @Override
    public void deleteCurrentUser() {
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_DELETE_SELF);
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_DELETE);
        getSpectatioUiUtil().wait5Seconds();
    }
    /** {@inheritDoc} */
    // check if a user is present in the list of existing users
    @Override
    public boolean isUserPresent(String user) {
        BySelector buttonSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.USER_SETTINGS_ADD_PROFILE);
        UiObject2 addUserButton =
                mScrollUtility.scrollAndFindUiObject(
                        mScrollAction,
                        mScrollDirection,
                        mForwardButtonSelector,
                        mBackwardButtonSelector,
                        mScrollableElementSelector,
                        buttonSelector,
                        String.format("Scroll to find %s", user));
        // Log.v(
        //         TAG,
        //        String.format(
        //              "AddProfileButton = %s ; UI_Obj = %s",
        //             AutomotiveConfigConstants.USER_SETTINGS_ADD_PROFILE, addUserButton));
        if (addUserButton == null) {
            clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MANAGE_OTHER_PROFILES);
            UiObject2 UserObject =
                    mScrollUtility.scrollAndFindUiObject(
                            mScrollAction,
                            mScrollDirection,
                            mForwardButtonSelector,
                            mBackwardButtonSelector,
                            mScrollableElementSelector,
                            By.text(user),
                            String.format("Scroll to find %s", user));
            getSpectatioUiUtil().wait1Second();
            return UserObject != null;
        }
        return false;
    }
    // switch User from current user to given user
    @Override
    public void switchUser(String userFrom, String userTo) {
        int count = 0;
        BySelector userFromSelector = By.text(userFrom);
        UiObject2 userFromObject = getSpectatioUiUtil().findUiObject(userFromSelector);
        getSpectatioUiUtil().validateUiObject(userFromObject, String.format("User %s", userFrom));
        getSpectatioUiUtil().clickAndWait(userFromObject);
        BySelector userToSelector = By.text(userTo);
        UiObject2 userToObject = getSpectatioUiUtil().findUiObject(userToSelector);
        getSpectatioUiUtil().validateUiObject(userToObject, String.format("User %s", userTo));
        getSpectatioUiUtil().clickAndWait(userToObject);
        BySelector homeSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.HOME_BOTTOM_CARD);
        getSpectatioUiUtil().waitForUiObject(homeSelector, WAIT_MS);
        skipSetupWizard();
    }

    @Override
    public void skipSetupWizard() {
        executeWorkflow(AutomotiveConfigConstants.SKIP_SETUP_WIZARD);
    }

    @Override
    public void switchUsingUserIcon(String userNameConfigKey) {
        int count = 0;
        clickbutton(AutomotiveConfigConstants.HOME_PROFILE_ICON_BUTTON);
        clickbutton(userNameConfigKey);
        skipSetupWizard();
        BySelector homeSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.HOME_BOTTOM_CARD);
        getSpectatioUiUtil().waitForUiObject(homeSelector, WAIT_MS);
    }
    @Override
    public String getProfileNameFromSettings() {
        BySelector profileNameSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.DEVICE_HEADER_TITLE);
        UiObject2 profileName = getSpectatioUiUtil().findUiObject(profileNameSelector);
        String profileNameText = profileName.getText();
        return profileNameText;
    }
    @Override
    public void editUserName(String name) {
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_RENAME);
        BySelector profileNameEditSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.USER_SETTINGS_PROFILE_NAME_EDIT);
        UiObject2 profileNameEdit = getSpectatioUiUtil().findUiObject(profileNameEditSelector);
        profileNameEdit.setText(name);
        getSpectatioUiUtil().wait1Second();
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_OK);
        getSpectatioUiUtil().wait1Second();
    }
    // add User via quick settings
    @Override
    public void addUserQuickSettings(String userFrom) {
        goToQuickSettings();
        getSpectatioUiUtil().wait1Second();
        addUser();
    }
    // make an existing user admin
    @Override
    public void makeUserAdmin(String user) {
        if (isUserPresent(user)) {
            BySelector userSelector = By.text(user);
            UiObject2 userObject = getSpectatioUiUtil().findUiObject(userSelector);
            getSpectatioUiUtil().validateUiObject(userObject, String.format("user %s", user));
            getSpectatioUiUtil().clickAndWait(userObject);
            clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MAKE_ADMIN);
            clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MAKE_ADMIN_CONFIRM);
        }
    }
    // click an on-screen element if expected text for that element is present
    private void clickbutton(String buttonText) {
        BySelector buttonSelector = getUiElementFromConfig(buttonText);
        UiObject2 buttonObject =
                mScrollUtility.scrollAndFindUiObject(
                        mScrollAction,
                        mScrollDirection,
                        mForwardButtonSelector,
                        mBackwardButtonSelector,
                        mScrollableElementSelector,
                        buttonSelector,
                        String.format("Scroll to find %s", buttonText));
        // Log.v(TAG, String.format("button =  %s ; UI_Obj = %s", buttonText, buttonObject));
        getSpectatioUiUtil().validateUiObject(buttonObject, String.format("button %s", buttonText));
        getSpectatioUiUtil().clickAndWait(buttonObject);
        getSpectatioUiUtil().wait1Second();
    }
    @Override
    public boolean isNewUserAnAdmin(String user) {
        boolean isUserAdmin = true;
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MANAGE_OTHER_PROFILES);
        UiObject2 UserObject =
                mScrollUtility.scrollAndFindUiObject(
                        mScrollAction,
                        mScrollDirection,
                        mForwardButtonSelector,
                        mBackwardButtonSelector,
                        mScrollableElementSelector,
                        By.text(user),
                        String.format("Scroll to find %s", user));
        getSpectatioUiUtil().clickAndWait(UserObject);
        getSpectatioUiUtil().wait1Second();
        if (getSpectatioUiUtil()
                .hasUiElement(
                        getUiElementFromConfig(
                                AutomotiveConfigConstants.USER_SETTINGS_MAKE_ADMIN))) {
            return !isUserAdmin;
        }
        return isUserAdmin;
    }
    // go to quick Settings for switching User
    private void goToQuickSettings() {
        clickbutton(AutomotiveConfigConstants.HOME_PROFILE_ICON_BUTTON);
    }
    // checks whether the Add profile button is visible
    @Override
    public boolean isVisibleAddProfile() {
        boolean isVisibleAddProfile = true;
        if (getSpectatioUiUtil()
                .hasUiElement(
                        getUiElementFromConfig(
                                AutomotiveConfigConstants.USER_SETTINGS_ADD_PROFILE))) {
            return isVisibleAddProfile;
        }
        return !isVisibleAddProfile;
    }
    @Override
    public boolean isToggleOn(String buttonText) {
        BySelector mEnableOptionSelector = getUiElementFromConfig(buttonText);
        mEnableOption =
                mScrollUtility.scrollAndFindUiObject(
                        mScrollAction,
                        mScrollDirection,
                        mForwardButtonSelector,
                        mBackwardButtonSelector,
                        mScrollableElementSelector,
                        mEnableOptionSelector,
                        String.format("Scroll to find %s", buttonText));
        getSpectatioUiUtil().validateUiObject(mEnableOption, buttonText);
        return mEnableOption.isChecked();
    }
    // Toggles the switch from one mode to the other
    @Override
    public boolean toggle(String buttonText) {
        boolean currentStatus = isToggleOn(buttonText);
        getSpectatioUiUtil().clickAndWait(mEnableOption, 10000);
        boolean finalStatus = isToggleOn(buttonText);
        return finalStatus != currentStatus;
    }

    @Override
    public void deleteAdminAndChooseOtherAsAdmin(String userName) {
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_DELETE_SELF);
        clickbutton(AutomotiveConfigConstants.CHOOSE_ADMIN_BUTTON);
        BySelector userSelector = By.text(userName);
        UiObject2 userObject = getSpectatioUiUtil().findUiObject(userSelector);
        getSpectatioUiUtil().clickAndWait(userObject);
        clickbutton(AutomotiveConfigConstants.MAKE_ADMIN_BUTTON);
        getSpectatioUiUtil()
                .waitNSeconds(
                        WAIT_MS); // WAIT_MS the time to wait (in msec) after user switch complete
        BySelector homeButtonSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.HOME_PROFILE_ICON_BUTTON);
        getSpectatioUiUtil().waitForUiObject(homeButtonSelector, WAIT_MS);
    }

    @Override
    public boolean checkUserProfileName(String initialUser, String newUser) {
        return initialUser.equals(newUser);
    }

    @Override
    public void chooseNewAdmin() {
        int count = 0;
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_CHOOSE_ADMIN);
        BySelector userTitleSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.HOME_SECONDARY_USER_BUTTON);
        UiObject2 userTitle = getSpectatioUiUtil().findUiObject(userTitleSelector);
        getSpectatioUiUtil().clickAndWait(userTitle);
        clickbutton(AutomotiveConfigConstants.USER_SETTINGS_MAKE_ADMIN_CONFIRM);
        BySelector homeBottomCardSelector =
                getUiElementFromConfig(AutomotiveConfigConstants.HOME_BOTTOM_CARD);
        getSpectatioUiUtil().waitForUiObject(homeBottomCardSelector, WAIT_MS);
    }
}
