/*
 * 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 com.android.settings.applications.appinfo;

import static com.android.settings.widget.EntityHeaderController.ActionType;

import android.app.Activity;
import android.app.LocaleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.UserHandle;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.preference.Preference;

import com.android.internal.app.LocaleHelper;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.AppLocaleUtil;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.widget.LayoutPreference;

import java.util.Locale;

/**
 * TODO(b/223503670): Implement the unittest.
 * A fragment to show the current app locale info.
 */
public class AppLocaleDetails extends SettingsPreferenceFragment {
    private static final String TAG = "AppLocaleDetails";

    private static final String KEY_APP_DESCRIPTION = "app_locale_description";
    private static final String KEY_APP_DISCLAIMER = "app_locale_disclaimer";

    private boolean mCreated = false;
    private String mPackageName;
    private LayoutPreference mPrefOfDescription;
    private Preference mPrefOfDisclaimer;
    private ApplicationInfo mApplicationInfo;
    @Nullable private String mParentLocale;

    /**
     * Create a instance of AppLocaleDetails.
     * @param packageName Indicates which application need to show the locale picker.
     * @param uid User id.
     */
    public static AppLocaleDetails newInstance(String packageName, int uid) {
        AppLocaleDetails appLocaleDetails = new AppLocaleDetails();
        Bundle bundle = new Bundle();
        bundle.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
        bundle.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
        appLocaleDetails.setArguments(bundle);
        return appLocaleDetails;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        mPackageName = bundle.getString(AppInfoBase.ARG_PACKAGE_NAME, "");
        if (mPackageName.isEmpty()) {
            Log.d(TAG, "There is no package name.");
            finish();
        }
        int uid = bundle.getInt(AppInfoBase.ARG_PACKAGE_UID, getContext().getUserId());

        addPreferencesFromResource(R.xml.app_locale_details);
        mPrefOfDescription = getPreferenceScreen().findPreference(KEY_APP_DESCRIPTION);
        mPrefOfDisclaimer = getPreferenceScreen().findPreference(KEY_APP_DISCLAIMER);
        mApplicationInfo = getApplicationInfo(mPackageName, uid);
        setDisclaimerPreference();
    }

    // Override here so we don't have an empty screen
    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container,
            Bundle savedInstanceState) {
        // if we don't have a package, show a page saying this is unsupported
        if (mPackageName.isEmpty()) {
            return inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        refreshUi();
        final Activity activity = getActivity();
        if (mParentLocale != null) {
            activity.setTitle(mParentLocale);
        } else {
            activity.setTitle(R.string.app_locale_picker_title);
        }
    }

    private void refreshUi() {
        setDescription();
    }

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.APPS_LOCALE_LIST;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (mCreated) {
            Log.w(TAG, "onActivityCreated: ignoring duplicate call");
            return;
        }
        mCreated = true;
        if (mPackageName == null) {
            return;
        }
        // Creates a head icon button of app on this page.
        final Activity activity = getActivity();
        final Preference pref = EntityHeaderController
                .newInstance(activity, this, null /* header */)
                .setIcon(Utils.getBadgedIcon(getContext(), mApplicationInfo))
                .setLabel(mApplicationInfo.loadLabel(getContext().getPackageManager()))
                .setIsInstantApp(AppUtils.isInstant(mApplicationInfo))
                .setPackageName(mPackageName)
                .setUid(mApplicationInfo.uid)
                .setHasAppInfoLink(true)
                .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
                .setOrder(10)
                .done(getPrefContext());
        getPreferenceScreen().addPreference(pref);
    }

    private void setDisclaimerPreference() {
        if (FeatureFlagUtils.isEnabled(
                getContext(), FeatureFlagUtils.SETTINGS_APP_LOCALE_OPT_IN_ENABLED)) {
            mPrefOfDisclaimer.setVisible(false);
        }
    }

    private void setDescription() {
        int res = getAppDescription();
        if (res != -1) {
            mPrefOfDescription.setVisible(true);
            TextView description = (TextView) mPrefOfDescription.findViewById(R.id.description);
            description.setText(getContext().getString(res));
        }
    }

    private ApplicationInfo getApplicationInfo(String packageName, int userId) {
        ApplicationInfo applicationInfo;
        try {
            applicationInfo = getContext().getPackageManager()
                    .getApplicationInfoAsUser(packageName, /* flags= */ 0, userId);
            return applicationInfo;
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Application info not found for: " + packageName);
            return null;
        }
    }

    private int getAppDescription() {
        LocaleList packageLocaleList = AppLocaleUtil.getPackageLocales(getContext(), mPackageName);
        String[] assetLocaleList = AppLocaleUtil.getAssetLocales(getContext(), mPackageName);
        // TODO add apended url string, "Learn more", to these both sentenses.
        if ((packageLocaleList != null && packageLocaleList.isEmpty())
                || (packageLocaleList == null && assetLocaleList.length == 0)) {
            return R.string.desc_no_available_supported_locale;
        }
        return -1;
    }

    /** Gets per app's default locale */
    public static Locale getAppDefaultLocale(Context context, String packageName) {
        LocaleManager localeManager = context.getSystemService(LocaleManager.class);
        try {
            LocaleList localeList = (localeManager == null)
                    ? null : localeManager.getApplicationLocales(packageName);
            return localeList == null ? null : localeList.get(0);
        } catch (IllegalArgumentException e) {
            Log.w(TAG, "package name : " + packageName + " is not correct. " + e);
        }
        return null;
    }

    /**
     * TODO (b209962418) Do a performance test to low end device.
     * @return Return the summary to show the current app's language.
     */
    public static CharSequence getSummary(Context context, ApplicationInfo app) {
        final UserHandle userHandle = UserHandle.getUserHandleForUid(app.uid);
        final Context contextAsUser = context.createContextAsUser(userHandle, 0);
        Locale appLocale = getAppDefaultLocale(contextAsUser, app.packageName);
        if (appLocale == null) {
            return context.getString(R.string.preference_of_system_locale_summary);
        } else {
            return LocaleHelper.getDisplayName(appLocale.stripExtensions(), appLocale, true);
        }
    }

    public void setParentLocale(@Nullable String localeName) {
        mParentLocale = localeName;
    }
}
