// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assert, assertNotReachedCase } from '//resources/js/assert.js';
import { isMac } from '//resources/js/platform.js';
import { hasKeyModifiers } from '//resources/js/util.js';
import { CrLitElement } from '//resources/lit/v3_0/lit.rollup.js';
import { getCss } from './cr_grid.css.js';
import { getHtml } from './cr_grid.html.js';
export class CrGridElement extends CrLitElement {
    static get is() {
        return 'cr-grid';
    }
    static get styles() {
        return getCss();
    }
    render() {
        return getHtml.bind(this)();
    }
    static get properties() {
        return {
            columns: { type: Number },
            disableArrowNavigation: { type: Boolean },
            focusSelector: { type: String },
            ignoreModifiedKeyEvents: { type: Boolean },
        };
    }
    #columns_accessor_storage = 1;
    get columns() { return this.#columns_accessor_storage; }
    set columns(value) { this.#columns_accessor_storage = value; }
    #disableArrowNavigation_accessor_storage = false;
    get disableArrowNavigation() { return this.#disableArrowNavigation_accessor_storage; }
    set disableArrowNavigation(value) { this.#disableArrowNavigation_accessor_storage = value; }
    #focusSelector_accessor_storage;
    get focusSelector() { return this.#focusSelector_accessor_storage; }
    set focusSelector(value) { this.#focusSelector_accessor_storage = value; }
    #ignoreModifiedKeyEvents_accessor_storage = false;
    get ignoreModifiedKeyEvents() { return this.#ignoreModifiedKeyEvents_accessor_storage; }
    set ignoreModifiedKeyEvents(value) { this.#ignoreModifiedKeyEvents_accessor_storage = value; }
    updated(changedProperties) {
        super.updated(changedProperties);
        if (changedProperties.has('columns')) {
            this.style.setProperty('--cr-grid-columns', String(this.columns));
        }
    }
    getSlottedParent_(element) {
        let parent = element;
        while (parent.assignedSlot !== this.$.items &&
            parent.parentElement !== null) {
            parent = parent.parentElement;
        }
        assert(parent);
        return parent;
    }
    onKeydown_(e) {
        if (e.key === ' ' || (e.key === 'Enter' && !(isMac && e.ctrlKey))) {
            e.preventDefault();
            e.stopPropagation();
            e.target.click();
            return;
        }
        if (this.disableArrowNavigation ||
            !['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {
            return;
        }
        const arrowKey = e.key;
        const items = this.$.items.assignedElements().filter(el => {
            return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
        });
        const currentIndex = items.indexOf(this.getSlottedParent_(e.target));
        const isRtl = window.getComputedStyle(this)['direction'] === 'rtl';
        const bottomRowColumns = items.length % this.columns;
        const direction = ['ArrowRight', 'ArrowDown'].includes(arrowKey) ? 1 : -1;
        const inEdgeRow = direction === 1 ?
            currentIndex >= items.length - bottomRowColumns :
            currentIndex < this.columns;
        let delta = 0;
        switch (arrowKey) {
            case 'ArrowLeft':
            case 'ArrowRight':
                // Ignores keys likely to be browse shortcuts (like Alt+Left for
                // back).
                if (this.ignoreModifiedKeyEvents && hasKeyModifiers(e)) {
                    return;
                }
                delta = direction * (isRtl ? -1 : 1);
                break;
            case 'ArrowUp':
            case 'ArrowDown':
                delta = direction * (inEdgeRow ? bottomRowColumns : this.columns);
                break;
            default:
                assertNotReachedCase(arrowKey);
        }
        // Handle cases where we move to an empty space in a non-full bottom row
        // and have to jump to the next row.
        if (arrowKey === 'ArrowUp' && inEdgeRow &&
            currentIndex >= bottomRowColumns) {
            delta -= this.columns;
        }
        else if (arrowKey === 'ArrowDown' && !inEdgeRow &&
            currentIndex + delta >= items.length) {
            delta += bottomRowColumns;
        }
        e.preventDefault();
        const newIndex = (items.length + currentIndex + delta) % items.length;
        const item = items[newIndex];
        const toFocus = this.focusSelector ?
            item.querySelector(this.focusSelector) :
            item;
        assert(toFocus);
        toFocus.focus();
        this.fire('cr-grid-focus-changed', toFocus);
    }
}
customElements.define(CrGridElement.is, CrGridElement);
