/*
 * Copyright (C) 2018 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 com.android.systemui.statusbar.car;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.GradientDrawable;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Displays a GridLayout with icons for the users in the system to allow switching between users.
 * One of the uses of this is for the lock screen in auto.
 */
public class UserGridRecyclerView extends RecyclerView implements
        UserManagerHelper.OnUsersUpdateListener {
    private UserSelectionListener mUserSelectionListener;
    private UserAdapter mAdapter;
    private UserManagerHelper mUserManagerHelper;
    private Context mContext;

    public UserGridRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setHasFixedSize(true);
        mContext = context;
        mUserManagerHelper = new UserManagerHelper(mContext);
    }

    /**
     * Register listener for any update to the users
     */
    @Override
    public void onFinishInflate() {
        mUserManagerHelper.registerOnUsersUpdateListener(this);
    }

    /**
     * Unregisters listener checking for any change to the users
     */
    @Override
    public void onDetachedFromWindow() {
        mUserManagerHelper.unregisterOnUsersUpdateListener();
    }

    /**
     * Initializes the adapter that populates the grid layout
     *
     * @return the adapter
     */
    public void buildAdapter() {
        List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
                .getAllUsers());
        mAdapter = new UserAdapter(mContext, userRecords);
        super.setAdapter(mAdapter);
    }

    private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
        List<UserRecord> userRecords = new ArrayList<>();
        for (UserInfo userInfo : userInfoList) {
            boolean isForeground = mUserManagerHelper.getForegroundUserId() == userInfo.id;
            UserRecord record = new UserRecord(userInfo, false /* isGuest */,
                    false /* isAddUser */, isForeground);
            userRecords.add(record);
        }

        // Add guest user record if the foreground user is not a guest
        if (!mUserManagerHelper.foregroundUserIsGuestUser()) {
            userRecords.add(addGuestUserRecord());
        }

        // Add add user record if the foreground user can add users
        if (mUserManagerHelper.foregroundUserCanAddUsers()) {
            userRecords.add(addUserRecord());
        }

        return userRecords;
    }

    /**
     * Create guest user record
     */
    private UserRecord addGuestUserRecord() {
        UserInfo userInfo = new UserInfo();
        userInfo.name = mContext.getString(R.string.car_guest);
        return new UserRecord(userInfo, true /* isGuest */,
                false /* isAddUser */, false /* isForeground */);
    }

    /**
     * Create add user record
     */
    private UserRecord addUserRecord() {
        UserInfo userInfo = new UserInfo();
        userInfo.name = mContext.getString(R.string.car_add_user);
        return new UserRecord(userInfo, false /* isGuest */,
                true /* isAddUser */, false /* isForeground */);
    }

    public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
        mUserSelectionListener = userSelectionListener;
    }

    @Override
    public void onUsersUpdate() {
        mAdapter.clearUsers();
        mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
        mAdapter.notifyDataSetChanged();
    }

    /**
     * Adapter to populate the grid layout with the available user profiles
     */
    public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder> {

        private final Context mContext;
        private List<UserRecord> mUsers;
        private final int mPodImageAvatarWidth;
        private final int mPodImageAvatarHeight;
        private final Resources mRes;
        private final String mGuestName;
        private final String mNewUserName;

        public UserAdapter(Context context, List<UserRecord> users) {
            mRes = context.getResources();
            mContext = context;
            updateUsers(users);
            mPodImageAvatarWidth = mRes.getDimensionPixelSize(
                    R.dimen.car_fullscreen_user_pod_image_avatar_width);
            mPodImageAvatarHeight = mRes.getDimensionPixelSize(
                    R.dimen.car_fullscreen_user_pod_image_avatar_height);
            mGuestName = mRes.getString(R.string.car_guest);
            mNewUserName = mRes.getString(R.string.car_new_user);
        }

        public void clearUsers() {
            mUsers.clear();
        }

        public void updateUsers(List<UserRecord> users) {
            mUsers = users;
        }

        @Override
        public UserAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext)
                    .inflate(R.layout.car_fullscreen_user_pod, parent, false);
            view.setAlpha(1f);
            view.bringToFront();
            return new UserAdapterViewHolder(view);
        }

        @Override
        public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
            UserRecord userRecord = mUsers.get(position);
            holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
            holder.mUserNameTextView.setText(userRecord.mInfo.name);
            holder.mView.setOnClickListener(v -> {
                if (userRecord == null) {
                    return;
                }

                // Notify the listener which user was selected
                if (mUserSelectionListener != null) {
                    mUserSelectionListener.onUserSelected(userRecord);
                }

                // If the user selects Guest, switch to Guest profile
                if (userRecord.mIsGuest) {
                    mUserManagerHelper.switchToGuest(mGuestName);
                    return;
                }

                // If the user wants to add a user, start task to add new user
                if (userRecord.mIsAddUser) {
                    new AddNewUserTask().execute(mNewUserName);
                    return;
                }

                // If the user doesn't want to be a guest or add a user, switch to the user selected
                mUserManagerHelper.switchToUser(userRecord.mInfo);
            });

        }

        private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {

            @Override
            protected UserInfo doInBackground(String... userNames) {
                return mUserManagerHelper.createNewUser(userNames[0]);
            }

            @Override
            protected void onPreExecute() {
            }

            @Override
            protected void onPostExecute(UserInfo user) {
                if (user != null) {
                    mUserManagerHelper.switchToUser(user);
                }
            }
        }

        @Override
        public int getItemCount() {
            return mUsers.size();
        }

        /**
         * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
         * the first character in the username.
         *
         * @param record the profile of the user for which the icon should be created
         */
        private Bitmap getDefaultUserIcon(UserRecord record) {
            CharSequence displayText;
            boolean isAddUserText = false;
            if (record.mIsAddUser) {
                displayText = "+";
                isAddUserText = true;
            } else {
                displayText = record.mInfo.name.subSequence(0, 1);
            }
            Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
                    Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(out);

            // Draw the circle background.
            GradientDrawable shape = new GradientDrawable();
            shape.setShape(GradientDrawable.RADIAL_GRADIENT);
            shape.setGradientRadius(1.0f);
            shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
            shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
            shape.draw(canvas);

            // Draw the letter in the center.
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
            paint.setTextAlign(Align.CENTER);
            if (isAddUserText) {
                paint.setTextSize(mRes.getDimensionPixelSize(
                        R.dimen.car_touch_target_size));
            } else {
                paint.setTextSize(mRes.getDimensionPixelSize(
                        R.dimen.car_fullscreen_user_pod_icon_text_size));
            }

            Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
            // The Y coordinate is measured by taking half the height of the pod, but that would
            // draw the character putting the bottom of the font in the middle of the pod.  To
            // correct this, half the difference between the top and bottom distance metrics of the
            // font gives the offset of the font.  Bottom is a positive value, top is negative, so
            // the different is actually a sum.  The "half" operation is then factored out.
            canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
                    (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);

            return out;
        }

        public class UserAdapterViewHolder extends RecyclerView.ViewHolder {

            public ImageView mUserAvatarImageView;
            public TextView mUserNameTextView;
            public View mView;

            public UserAdapterViewHolder(View view) {
                super(view);
                mView = view;
                mUserAvatarImageView = (ImageView) view.findViewById(R.id.user_avatar);
                mUserNameTextView = (TextView) view.findViewById(R.id.user_name);
            }
        }
    }

    /**
     * Object wrapper class for the userInfo.  Use it to distinguish if a profile is a
     * guest profile, add user profile, or the foreground user.
     */
    public static final class UserRecord {

        public final UserInfo mInfo;
        public final boolean mIsGuest;
        public final boolean mIsAddUser;
        public final boolean mIsForeground;

        public UserRecord(UserInfo userInfo, boolean isGuest, boolean isAddUser,
                boolean isForeground) {
            mInfo = userInfo;
            mIsGuest = isGuest;
            mIsAddUser = isAddUser;
            mIsForeground = isForeground;
        }
    }

    /**
     * Listener used to notify when a user has been selected
     */
    interface UserSelectionListener {

        void onUserSelected(UserRecord record);
    }
}
