/*
 * Copyright (C) 2019 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.permissioncontroller.permission.ui.auto;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.ArrayMap;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;

import com.android.permissioncontroller.R;
import com.android.permissioncontroller.auto.AutoSettingsFrameFragment;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.legacy.PermissionApps;
import com.android.permissioncontroller.permission.model.legacy.PermissionApps.Callback;
import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment;
import com.android.permissioncontroller.permission.ui.handheld.PermissionControlPreference;
import com.android.permissioncontroller.permission.utils.Utils;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Map;

/** Shows the list of applications which have (or do not have) the given permission. */
public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implements Callback {

    private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem";
    private static final String KEY_ALLOWED_PERMISSIONS_GROUP = "allowed_permissions_group";
    private static final String KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP =
            "allowed_foreground_permissions_group";
    private static final String KEY_DENIED_PERMISSIONS_GROUP = "denied_permissions_group";

    private static final String SHOW_SYSTEM_KEY = AutoPermissionAppsFragment.class.getName()
            + KEY_SHOW_SYSTEM_PREFS;

    /** Creates a new instance of {@link AutoPermissionAppsFragment} for the given permission. */
    public static AutoPermissionAppsFragment newInstance(String permissionName) {
        return setPermissionName(new AutoPermissionAppsFragment(), permissionName);
    }

    private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) {
        Bundle arguments = new Bundle();
        arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName);
        fragment.setArguments(arguments);
        return fragment;
    }

    private PermissionApps mPermissionApps;

    private boolean mShowSystem;
    private boolean mHasSystemApps;

    private Collator mCollator;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY);
        }

        setLoading(true);

        String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
        mPermissionApps = new PermissionApps(getActivity(), groupName, /* callback= */ this);
        mPermissionApps.refresh(/* getUiInfo= */ true);

        mCollator = Collator.getInstance(
                getContext().getResources().getConfiguration().getLocales().get(0));

        setShowSystemAppsToggle();
        bindUi(mPermissionApps, groupName);
    }

    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem);
    }

    @Override
    public void onStart() {
        super.onStart();
        mPermissionApps.refresh(/* getUiInfo= */ true);
    }

    private void setShowSystemAppsToggle() {
        if (!mHasSystemApps) {
            setAction(/* label= */ null, /* onClickListener= */ null);
            return;
        }

        // Show the opposite label from the current state.
        String label;
        if (mShowSystem) {
            label = getString(R.string.menu_hide_system);
        } else {
            label = getString(R.string.menu_show_system);
        }

        setAction(label, v -> {
            mShowSystem = !mShowSystem;
            if (mPermissionApps.getApps() != null) {
                onPermissionsLoaded(mPermissionApps);
            }
            setShowSystemAppsToggle();
        });
    }

    private void bindUi(PermissionApps permissionApps, @NonNull String groupName) {
        CharSequence label = permissionApps.getFullLabel();
        setHeaderLabel(label);

        Drawable icon = permissionApps.getIcon();
        Preference header = new Preference(getContext());
        header.setTitle(label);
        header.setIcon(icon);
        header.setSummary(Utils.getPermissionGroupDescriptionString(getContext(), groupName,
                permissionApps.getDescription()));
        getPreferenceScreen().addPreference(header);

        PreferenceGroup allowed = new PreferenceCategory(getContext());
        allowed.setKey(KEY_ALLOWED_PERMISSIONS_GROUP);
        allowed.setTitle(R.string.allowed_header);
        allowed.setVisible(false);
        getPreferenceScreen().addPreference(allowed);

        PreferenceGroup foreground = new PreferenceCategory(getContext());
        foreground.setKey(KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
        foreground.setTitle(R.string.allowed_foreground_header);
        foreground.setVisible(false);
        getPreferenceScreen().addPreference(foreground);

        PreferenceGroup denied = new PreferenceCategory(getContext());
        denied.setKey(KEY_DENIED_PERMISSIONS_GROUP);
        denied.setTitle(R.string.denied_header);
        denied.setVisible(false);
        getPreferenceScreen().addPreference(denied);
    }

    @Override
    public void onPermissionsLoaded(PermissionApps permissionApps) {
        Context context = getPreferenceManager().getContext();

        if (context == null || getActivity() == null) {
            return;
        }

        PreferenceCategory allowed = findPreference(KEY_ALLOWED_PERMISSIONS_GROUP);
        PreferenceCategory allowedForeground = findPreference(
                KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
        PreferenceCategory denied = findPreference(KEY_DENIED_PERMISSIONS_GROUP);

        allowed.setOrderingAsAdded(true);
        allowedForeground.setOrderingAsAdded(true);
        denied.setOrderingAsAdded(true);

        Map<String, Preference> existingPrefs = new ArrayMap<>();
        int numPreferences = allowed.getPreferenceCount();
        for (int i = 0; i < numPreferences; i++) {
            Preference preference = allowed.getPreference(i);
            existingPrefs.put(preference.getKey(), preference);
        }
        allowed.removeAll();
        numPreferences = allowedForeground.getPreferenceCount();
        for (int i = 0; i < numPreferences; i++) {
            Preference preference = allowedForeground.getPreference(i);
            existingPrefs.put(preference.getKey(), preference);
        }
        allowedForeground.removeAll();
        numPreferences = denied.getPreferenceCount();
        for (int i = 0; i < numPreferences; i++) {
            Preference preference = denied.getPreference(i);
            existingPrefs.put(preference.getKey(), preference);
        }
        denied.removeAll();

        mHasSystemApps = false;
        boolean hasPermissionWithBackgroundMode = false;

        ArrayList<PermissionApps.PermissionApp> sortedApps = new ArrayList<>(
                permissionApps.getApps());
        sortedApps.sort((x, y) -> {
            int result = mCollator.compare(x.getLabel(), y.getLabel());
            if (result == 0) {
                result = x.getUid() - y.getUid();
            }
            return result;
        });

        for (int i = 0; i < sortedApps.size(); i++) {
            PermissionApps.PermissionApp app = sortedApps.get(i);
            AppPermissionGroup group = app.getPermissionGroup();

            hasPermissionWithBackgroundMode =
                    hasPermissionWithBackgroundMode || group.hasPermissionWithBackgroundMode();

            if (!Utils.shouldShowPermission(getContext(), group)) {
                continue;
            }

            if (!app.getAppInfo().enabled) {
                continue;
            }

            String key = app.getKey();
            Preference existingPref = existingPrefs.get(key);
            if (existingPref != null) {
                // Without this, existing preferences remember their old order.
                existingPref.setOrder(Preference.DEFAULT_ORDER);
            }

            boolean isSystemApp = !Utils.isGroupOrBgGroupUserSensitive(group);

            if (isSystemApp) {
                mHasSystemApps = true;
            }

            if (isSystemApp && !mShowSystem) {
                continue;
            }

            PreferenceCategory category;
            if (group.areRuntimePermissionsGranted()) {
                if (!group.hasPermissionWithBackgroundMode()
                        || (group.getBackgroundPermissions() != null
                        && group.getBackgroundPermissions().areRuntimePermissionsGranted())) {
                    category = allowed;
                } else {
                    category = allowedForeground;
                }
            } else {
                category = denied;
            }

            if (existingPref != null) {
                category.addPreference(existingPref);
                continue;
            }

            PermissionControlPreference pref = new PermissionControlPreference(context, group,
                    PermissionAppsFragment.class.getName());
            pref.setKey(key);
            pref.setIcon(app.getIcon());
            pref.setTitle(Utils.getFullAppLabel(app.getAppInfo(), context));
            pref.setEllipsizeEnd();
            pref.useSmallerIcon();
            category.addPreference(pref);
        }

        if (hasPermissionWithBackgroundMode) {
            allowed.setTitle(R.string.allowed_always_header);
        }

        if (allowed.getPreferenceCount() == 0) {
            Preference empty = new Preference(context);
            empty.setTitle(R.string.no_apps_allowed);
            empty.setSelectable(false);
            allowed.addPreference(empty);
        }
        allowed.setVisible(true);

        allowedForeground.setVisible(allowedForeground.getPreferenceCount() > 0);

        if (denied.getPreferenceCount() == 0) {
            Preference empty = new Preference(context);
            empty.setTitle(R.string.no_apps_denied);
            empty.setSelectable(false);
            denied.addPreference(empty);
        }
        denied.setVisible(true);

        setShowSystemAppsToggle();
        setLoading(false);
    }
}
