/*
 * Copyright (C) 2020 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.car.systembar;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;

import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;

import com.android.systemui.dagger.SysUISingleton;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;

/**
 * CarSystemBarButtons can optionally have selection state that toggles certain visual indications
 * based on whether the active application on screen is associated with it. This is basically a
 * similar concept to a radio button group.
 *
 * This class controls the selection state of CarSystemBarButtons that have opted in to have such
 * selection state-dependent visual indications.
 */
@SysUISingleton
public class ButtonSelectionStateController {
    private static final String TAG = ButtonSelectionStateController.class.getSimpleName();

    private final Set<CarSystemBarButton> mRegisteredViews = new HashSet<>();

    protected ButtonMap mButtonsByCategory = new ButtonMap();
    protected ButtonMap mButtonsByPackage = new ButtonMap();
    protected ButtonMap mButtonsByComponentName = new ButtonMap();
    protected HashSet<CarSystemBarButton> mSelectedButtons;
    protected Context mContext;

    @Inject
    public ButtonSelectionStateController(Context context) {
        mContext = context;
        mSelectedButtons = new HashSet<>();
    }

    /**
     * Iterate through a view looking for CarSystemBarButton and add it to the controller if it
     * opted in to be highlighted when the active application is associated with it.
     *
     * @param v the View that may contain CarFacetButtons
     */
    protected void addAllButtonsWithSelectionState(View v) {
        if (v instanceof CarSystemBarButton) {
            if (((CarSystemBarButton) v).hasSelectionState()) {
                addButtonWithSelectionState((CarSystemBarButton) v);
            }
        } else if (v instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) v;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                addAllButtonsWithSelectionState(viewGroup.getChildAt(i));
            }
        }
    }

    /** Removes all buttons from the button maps. */
    protected void removeAll() {
        mButtonsByCategory.clear();
        mButtonsByPackage.clear();
        mButtonsByComponentName.clear();
        mSelectedButtons.clear();
        mRegisteredViews.clear();
    }

    /**
     * This will unselect the currently selected CarSystemBarButton and determine which one should
     * be selected next. It does this by reading the properties on the CarSystemBarButton and
     * seeing if they are a match with the supplied StackInfo list.
     * The order of selection detection is ComponentName, PackageName then Category
     * They will then be compared with the supplied StackInfo list.
     * The StackInfo is expected to be supplied in order of recency and StackInfo will only be used
     * for consideration if it has the same displayId as the CarSystemBarButton.
     *
     * @param taskInfoList of the currently running application
     * @param validDisplay index of the valid display
     */

    protected void taskChanged(List<RootTaskInfo> taskInfoList, int validDisplay) {
        RootTaskInfo validTaskInfo = null;
        for (RootTaskInfo taskInfo : taskInfoList) {
            // Find the first stack info with a topActivity in the primary display.
            // TODO: We assume that CarFacetButton will launch an app only in the primary display.
            // We need to extend the functionality to handle the multiple display properly.
            if (taskInfo.topActivity != null && taskInfo.displayId == validDisplay) {
                validTaskInfo = taskInfo;
                break;
            }
        }

        if (validTaskInfo == null) {
            // No stack was found that was on the same display as the buttons thus return
            return;
        }
        int displayId = validTaskInfo.displayId;

        // Clear all registered views
        mRegisteredViews.forEach(carSystemBarButton -> {
            if (carSystemBarButton.getDisplayId() == displayId) {
                carSystemBarButton.setSelected(false);
            }
        });
        mSelectedButtons.clear();

        HashSet<CarSystemBarButton> selectedButtons = findSelectedButtons(validTaskInfo);

        if (selectedButtons != null) {
            selectedButtons.forEach(carSystemBarButton -> {
                if (carSystemBarButton.getDisplayId() == displayId) {
                    carSystemBarButton.setSelected(true);
                    mSelectedButtons.add(carSystemBarButton);
                }
            });
        }
    }

    /**
     * Defaults to Display.DEFAULT_DISPLAY when no parameter is provided for the validDisplay.
     *
     * @param taskInfoList
     */
    protected void taskChanged(List<RootTaskInfo> taskInfoList) {
        taskChanged(taskInfoList, Display.DEFAULT_DISPLAY);
    }

    /**
     * Add navigation button to this controller if it uses selection state.
     */
    private void addButtonWithSelectionState(CarSystemBarButton carSystemBarButton) {
        if (mRegisteredViews.contains(carSystemBarButton)) {
            return;
        }
        String[] categories = carSystemBarButton.getCategories();
        for (int i = 0; i < categories.length; i++) {
            mButtonsByCategory.add(categories[i], carSystemBarButton);
        }

        String[] packages = carSystemBarButton.getPackages();
        for (int i = 0; i < packages.length; i++) {
            mButtonsByPackage.add(packages[i], carSystemBarButton);
        }
        String[] componentNames = carSystemBarButton.getComponentName();
        for (int i = 0; i < componentNames.length; i++) {
            mButtonsByComponentName.add(componentNames[i], carSystemBarButton);
        }

        mRegisteredViews.add(carSystemBarButton);
    }

    private HashSet<CarSystemBarButton> findSelectedButtons(RootTaskInfo validTaskInfo) {
        ComponentName topActivity = null;

        // Window mode being WINDOW_MODE_MULTI_WINDOW implies TaskView might be visible on the
        // display. In such cases, topActivity reported by validTaskInfo will be the one hosted in
        // TaskView and not necessarily the main activity visible on display. Thus we should get
        // rootTaskInfo instead.
        if (validTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
            try {
                RootTaskInfo rootTaskInfo =
                        ActivityTaskManager.getService().getRootTaskInfoOnDisplay(
                                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_UNDEFINED,
                                validTaskInfo.displayId);
                topActivity = rootTaskInfo.topActivity;
            } catch (RemoteException e) {
                Log.e(TAG, "findSelectedButtons: Failed getting root task info", e);
            }
        } else {
            topActivity = validTaskInfo.topActivity;
        }

        if (topActivity == null) return null;

        String packageName = topActivity.getPackageName();

        HashSet<CarSystemBarButton> selectedButtons =
                findButtonsByComponentName(topActivity);
        if (selectedButtons == null) {
            selectedButtons = mButtonsByPackage.get(packageName);
        }
        if (selectedButtons == null) {
            String category = getPackageCategory(packageName);
            if (category != null) {
                selectedButtons = mButtonsByCategory.get(category);
            }
        }

        return selectedButtons;
    }

    private HashSet<CarSystemBarButton> findButtonsByComponentName(
            ComponentName componentName) {
        HashSet<CarSystemBarButton> buttons =
                mButtonsByComponentName.get(componentName.flattenToShortString());
        return (buttons != null) ? buttons :
                mButtonsByComponentName.get(componentName.flattenToString());
    }

    private String getPackageCategory(String packageName) {
        PackageManager pm = mContext.getPackageManager();
        Set<String> supportedCategories = mButtonsByCategory.keySet();
        for (String category : supportedCategories) {
            Intent intent = new Intent();
            intent.setPackage(packageName);
            intent.setAction(Intent.ACTION_MAIN);
            intent.addCategory(category);
            List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
            if (list.size() > 0) {
                // Cache this package name into ButtonsByPackage map, so we won't have to query
                // all categories next time this package name shows up.
                mButtonsByPackage.put(packageName, mButtonsByCategory.get(category));
                return category;
            }
        }
        return null;
    }

    // simple multi-map
    private static class ButtonMap extends HashMap<String, HashSet<CarSystemBarButton>> {

        public boolean add(String key, CarSystemBarButton value) {
            if (containsKey(key)) {
                return get(key).add(value);
            }
            HashSet<CarSystemBarButton> set = new HashSet<>();
            set.add(value);
            put(key, set);
            return true;
        }
    }
}
