// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
 * @fileoverview 'settings-languages-page' is the settings page
 * for language and input method settings.
 */
// clang-format off
import 'chrome://resources/cr_components/managed_dialog/managed_dialog.js';
import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
import 'chrome://resources/cr_elements/icons.html.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import 'chrome://resources/js/action_link.js';
import 'chrome://resources/cr_elements/action_link.css.js';
import 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
import './add_languages_dialog.js';
import '../icons.html.js';
import '../relaunch_confirmation_dialog.js';
import '../settings_page/settings_section.js';
import '../settings_shared.css.js';
import '../settings_vars.css.js';
import { assert } from 'chrome://resources/js/assert.js';
import { isWindows } from 'chrome://resources/js/platform.js';
import { focusWithoutInk } from 'chrome://resources/js/focus_without_ink.js';
import { I18nMixin } from 'chrome://resources/cr_elements/i18n_mixin.js';
import { PolymerElement } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
// 
import { PrefsMixin } from '/shared/settings/prefs/prefs_mixin.js';
import { RelaunchMixin } from '../relaunch_mixin.js';
import { routes } from '../route.js';
import { RouteObserverMixin } from '../router.js';
import { getTemplate } from './languages_page.html.js';
import { LanguageSettingsActionType, LanguageSettingsMetricsProxyImpl, LanguageSettingsPageImpressionType } from './languages_settings_metrics_proxy.js';
import { getLanguageHelperInstance } from './languages.js';
import { convertLanguageCodeForTranslate } from './languages_util.js';
// clang-format on
/**
 * Millisecond delay that can be used when closing an action menu to keep it
 * briefly on-screen.
 */
export const kMenuCloseDelay = 100;
const SettingsLanguagesPageElementBase = RouteObserverMixin(RelaunchMixin(I18nMixin(PrefsMixin(PolymerElement))));
export class SettingsLanguagesPageElement extends SettingsLanguagesPageElementBase {
    static get is() {
        return 'settings-languages-page';
    }
    static get template() {
        return getTemplate();
    }
    static get properties() {
        return {
            /**
             * Read-only reference to the languages model provided by the
             * 'settings-languages' instance.
             */
            languages: Object,
            /**
             * The language to display the details for.
             */
            detailLanguage_: Object,
            showAddLanguagesDialog_: Boolean,
            addLanguagesDialogLanguages_: Array,
            showManagedLanguageDialog_: {
                type: Boolean,
                value: false,
            },
        };
    }
    languageHelper_;
    languageSettingsMetricsProxy_ = LanguageSettingsMetricsProxyImpl.getInstance();
    // 
    connectedCallback() {
        super.connectedCallback();
        this.languageHelper_ = getLanguageHelperInstance();
    }
    /**
     * Stamps and opens the Add Languages dialog, registering a listener to
     * disable the dialog's dom-if again on close.
     */
    onAddLanguagesClick_(e) {
        e.preventDefault();
        assert(this.languages);
        this.languageSettingsMetricsProxy_.recordPageImpressionMetric(LanguageSettingsPageImpressionType.ADD_LANGUAGE);
        this.addLanguagesDialogLanguages_ = this.languages.supported.filter(language => this.languageHelper_.canEnableLanguage(language));
        this.showAddLanguagesDialog_ = true;
    }
    onLanguagesAdded_(e) {
        const languagesToAdd = e.detail;
        languagesToAdd.forEach(languageCode => {
            this.languageHelper_.enableLanguage(languageCode);
            LanguageSettingsMetricsProxyImpl.getInstance().recordSettingsMetric(LanguageSettingsActionType.LANGUAGE_ADDED);
        });
    }
    onAddLanguagesDialogClose_() {
        this.showAddLanguagesDialog_ = false;
        this.addLanguagesDialogLanguages_ = null;
        const toFocus = this.shadowRoot.querySelector('#addLanguages');
        assert(toFocus);
        focusWithoutInk(toFocus);
    }
    /**
     * Formats language index (zero-indexed)
     */
    formatIndex_(index) {
        return (index + 1).toLocaleString();
    }
    /**
     * Checks if there are supported languages that are not enabled but can be
     * enabled.
     * @return True if there is at least one available language.
     */
    canEnableSomeSupportedLanguage_(languages) {
        return languages !== undefined && languages.supported.some(language => {
            // Need to call getLanguageHelperInstance() instead of
            // this.languageHelper_ here, because Polymer observers fire before
            // connectedCallback sometimes.
            return getLanguageHelperInstance().canEnableLanguage(language);
        });
    }
    /**
     * Used to determine which "Move" buttons to show for ordering enabled
     * languages.
     * @return True if |language| is at the |n|th index in the list of enabled
     *     languages.
     */
    isNthLanguage_(n) {
        if (this.languages === undefined || this.detailLanguage_ === undefined) {
            return false;
        }
        if (n >= this.languages.enabled.length) {
            return false;
        }
        const compareLanguage = this.languages.enabled[n];
        return this.detailLanguage_.language === compareLanguage.language;
    }
    /**
     * @return True if the "Move to top" option for |language| should be visible.
     */
    showMoveUp_() {
        // "Move up" is a no-op for the top language, and redundant with
        // "Move to top" for the 2nd language.
        return !this.isNthLanguage_(0) && !this.isNthLanguage_(1);
    }
    /**
     * @return True if the "Move down" option for |language| should be visible.
     */
    showMoveDown_() {
        return this.languages !== undefined &&
            !this.isNthLanguage_(this.languages.enabled.length - 1);
    }
    /**
     * @param languageCode The language code identifying a language.
     * @param translateTarget The target language.
     * @return 'target' if |languageCode| matches the target language,
     *     'non-target' otherwise.
     */
    isTranslationTarget_(languageCode, translateTarget) {
        if (convertLanguageCodeForTranslate(languageCode) === translateTarget) {
            return 'target';
        }
        else {
            return 'non-target';
        }
    }
    // 
    /**
     * Moves the language to the top of the list.
     */
    onMoveToTopClick_() {
        this.$.menu.get().close();
        if (this.detailLanguage_.isForced) {
            // If language is managed, show dialog to inform user it can't be modified
            this.showManagedLanguageDialog_ = true;
            return;
        }
        this.languageHelper_.moveLanguageToFront(this.detailLanguage_.language.code);
        this.languageSettingsMetricsProxy_.recordSettingsMetric(LanguageSettingsActionType.LANGUAGE_LIST_REORDERED);
    }
    /**
     * Moves the language up in the list.
     */
    onMoveUpClick_() {
        this.$.menu.get().close();
        if (this.detailLanguage_.isForced) {
            // If language is managed, show dialog to inform user it can't be modified
            this.showManagedLanguageDialog_ = true;
            return;
        }
        this.languageHelper_.moveLanguage(this.detailLanguage_.language.code, true /* upDirection */);
        this.languageSettingsMetricsProxy_.recordSettingsMetric(LanguageSettingsActionType.LANGUAGE_LIST_REORDERED);
    }
    /**
     * Moves the language down in the list.
     */
    onMoveDownClick_() {
        this.$.menu.get().close();
        if (this.detailLanguage_.isForced) {
            // If language is managed, show dialog to inform user it can't be modified
            this.showManagedLanguageDialog_ = true;
            return;
        }
        this.languageHelper_.moveLanguage(this.detailLanguage_.language.code, false /* upDirection */);
        this.languageSettingsMetricsProxy_.recordSettingsMetric(LanguageSettingsActionType.LANGUAGE_LIST_REORDERED);
    }
    /**
     * Disables the language.
     */
    onRemoveLanguageClick_() {
        this.$.menu.get().close();
        if (this.detailLanguage_.isForced) {
            // If language is managed, show dialog to inform user it can't be modified
            this.showManagedLanguageDialog_ = true;
            return;
        }
        this.languageHelper_.disableLanguage(this.detailLanguage_.language.code);
        this.languageSettingsMetricsProxy_.recordSettingsMetric(LanguageSettingsActionType.LANGUAGE_REMOVED);
    }
    /**
     * Returns either the "selected" class, if the language matches the
     * prospective UI language, or an empty string. Languages can only be
     * selected on Chrome OS and Windows.
     * @param languageCode The language code identifying a language.
     * @param prospectiveUILanguage The prospective UI language.
     * @return The class name for the language item.
     */
    getLanguageItemClass_(languageCode, prospectiveUILanguage) {
        if (isWindows && languageCode === prospectiveUILanguage) {
            return 'selected';
        }
        return '';
    }
    onDotsClick_(e) {
        // Set a copy of the LanguageState object since it is not data-bound to
        // the languages model directly.
        this.detailLanguage_ = Object.assign({}, e.model.item);
        this.$.menu.get().showAt(e.target);
        this.languageSettingsMetricsProxy_.recordPageImpressionMetric(LanguageSettingsPageImpressionType.LANGUAGE_OVERFLOW_MENU_OPENED);
    }
    /**
     * Closes the shared action menu after a short delay, so when a checkbox is
     * clicked it can be seen to change state before disappearing.
     */
    closeMenuSoon_() {
        const menu = this.$.menu.get();
        setTimeout(function () {
            if (menu.open) {
                menu.close();
            }
        }, kMenuCloseDelay);
    }
    /**
     * Triggered when the managed language dialog is dismissed.
     */
    onManagedLanguageDialogClosed_() {
        this.showManagedLanguageDialog_ = false;
    }
    currentRouteChanged(currentRoute) {
        if (currentRoute === routes.LANGUAGES) {
            this.languageSettingsMetricsProxy_.recordPageImpressionMetric(LanguageSettingsPageImpressionType.MAIN);
        }
    }
}
customElements.define(SettingsLanguagesPageElement.is, SettingsLanguagesPageElement);
