// 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-edit-dictionary-page' is a sub-page for editing
 * the "dictionary" of custom words used for spell check.
 */
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.js';
import 'chrome://resources/cr_elements/icons.html.js';
import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
import '/shared/settings/prefs/prefs.js';
import '../settings_page/settings_subpage.js';
import '../settings_shared.css.js';
import '../settings_vars.css.js';
import { flush, PolymerElement } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import { GlobalScrollTargetMixin } from '../global_scroll_target_mixin.js';
import { loadTimeData } from '../i18n_setup.js';
import { routes } from '../route.js';
import { SettingsViewMixin } from '../settings_page/settings_view_mixin.js';
import { getTemplate } from './edit_dictionary_page.html.js';
import { LanguagesBrowserProxyImpl } from './languages_browser_proxy.js';
// Max valid word size defined in
// https://cs.chromium.org/chromium/src/components/spellcheck/common/spellcheck_common.h?l=28
const MAX_CUSTOM_DICTIONARY_WORD_BYTES = 99;
const SettingsEditDictionaryPageElementBase = SettingsViewMixin(GlobalScrollTargetMixin(PolymerElement));
export class SettingsEditDictionaryPageElement extends SettingsEditDictionaryPageElementBase {
    static get is() {
        return 'settings-edit-dictionary-page';
    }
    static get template() {
        return getTemplate();
    }
    static get properties() {
        return {
            prefs: Object,
            newWordValue_: {
                type: String,
                value: '',
            },
            /**
             * Needed by GlobalScrollTargetMixin.
             */
            subpageRoute: {
                type: Object,
                value: routes.EDIT_DICTIONARY,
            },
            words_: {
                type: Array,
                value() {
                    return [];
                },
            },
            hasWords_: {
                type: Boolean,
                value: false,
            },
        };
    }
    languageSettingsPrivate_ = null;
    ready() {
        super.ready();
        this.languageSettingsPrivate_ =
            LanguagesBrowserProxyImpl.getInstance().getLanguageSettingsPrivate();
        this.languageSettingsPrivate_.getSpellcheckWords().then(words => {
            this.hasWords_ = words.length > 0;
            this.words_ = words;
        });
        this.languageSettingsPrivate_.onCustomDictionaryChanged.addListener(this.onCustomDictionaryChanged_.bind(this));
    }
    /**
     * Adds the word in the new-word input to the dictionary.
     */
    addWordFromInput_() {
        // Spaces are allowed, but removing leading and trailing whitespace.
        const word = this.getTrimmedNewWord_();
        this.newWordValue_ = '';
        if (word) {
            this.languageSettingsPrivate_.addSpellcheckWord(word);
        }
    }
    /**
     * Check if the field is empty or invalid.
     */
    disableAddButton_() {
        return this.getTrimmedNewWord_().length === 0 || this.isWordInvalid_();
    }
    getErrorMessage_() {
        if (this.newWordIsTooLong_()) {
            return loadTimeData.getString('addDictionaryWordLengthError');
        }
        if (this.newWordAlreadyAdded_()) {
            return loadTimeData.getString('addDictionaryWordDuplicateError');
        }
        return '';
    }
    getTrimmedNewWord_() {
        return this.newWordValue_.trim();
    }
    /**
     * If the word is invalid, returns true (or a message if one is provided).
     * Otherwise returns false.
     */
    isWordInvalid_() {
        return this.newWordAlreadyAdded_() || this.newWordIsTooLong_();
    }
    newWordAlreadyAdded_() {
        return this.words_.includes(this.getTrimmedNewWord_());
    }
    newWordIsTooLong_() {
        return this.getTrimmedNewWord_().length > MAX_CUSTOM_DICTIONARY_WORD_BYTES;
    }
    /**
     * Handles tapping on the Add Word button.
     */
    onAddWordClick_() {
        this.addWordFromInput_();
        this.$.newWord.focus();
    }
    /**
     * Handles updates to the word list. Additions are unshifted to the top
     * of the list so that users can see them easily.
     */
    onCustomDictionaryChanged_(added, removed) {
        const wasEmpty = this.words_.length === 0;
        for (const word of removed) {
            const index = this.words_.indexOf(word);
            if (index !== -1) {
                this.splice('words_', index, 1);
            }
        }
        if (this.words_.length === 0 && added.length === 0 && !wasEmpty) {
            this.hasWords_ = false;
        }
        // This is a workaround to ensure the dom-if is set to true before items
        // are rendered so that focus works correctly in Polymer 2; see
        // https://crbug.com/41430384.
        if (wasEmpty && added.length > 0) {
            this.hasWords_ = true;
        }
        for (const word of added) {
            if (!this.words_.includes(word)) {
                this.unshift('words_', word);
            }
        }
        // When adding a word to an _empty_ list, the template is expanded. This
        // is a workaround to resize the iron-list as well.
        // TODO(dschuyler): Remove this hack after iron-list no longer needs
        // this workaround to update the list at the same time the template
        // wrapping the list is expanded.
        if (wasEmpty && this.words_.length > 0) {
            flush();
            this.shadowRoot.querySelector('iron-list').notifyResize();
        }
    }
    /**
     * Handles Enter and Escape key presses for the new-word input.
     */
    onKeysPress_(e) {
        if (e.key === 'Enter' && !this.disableAddButton_()) {
            this.addWordFromInput_();
        }
        else if (e.key === 'Escape') {
            e.target.value = '';
        }
    }
    /**
     * Handles tapping on a "Remove word" icon button.
     */
    onRemoveWordClick_(e) {
        this.languageSettingsPrivate_.removeSpellcheckWord(e.model.item);
    }
    // SettingsViewMixin implementation.
    focusBackButton() {
        this.shadowRoot.querySelector('settings-subpage').focusBackButton();
    }
}
customElements.define(SettingsEditDictionaryPageElement.is, SettingsEditDictionaryPageElement);
