// Copyright 2017 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 } from 'chrome://resources/js/assert.js';
import { CrRouter } from 'chrome://resources/js/cr_router.js';
import { EventTracker } from 'chrome://resources/js/event_tracker.js';
import { selectFolder, setSearchTerm } from './actions.js';
import { ROOT_NODE_ID } from './constants.js';
import { Store } from './store.js';
/**
 * This element is a one way bound interface that routes the page URL to
 * the searchTerm and selectedId. Clients must initialize themselves by
 * reading the router's fields after attach.
 */
export class BookmarksRouter {
    searchTerm_ = '';
    selectedId_ = '';
    defaultId_ = '';
    updateStateTimeout_ = null;
    tracker_ = new EventTracker();
    initialize() {
        const store = Store.getInstance();
        store.addObserver(this);
        if (store.isInitialized()) {
            this.onStateChanged(store.data);
        }
        const router = CrRouter.getInstance();
        router.setDwellTime(200);
        this.onQueryParamsChanged_(router.getQueryParams());
        this.tracker_.add(router, 'cr-router-query-params-changed', (e) => this.onQueryParamsChanged_(e.detail));
    }
    teardown() {
        if (this.updateStateTimeout_) {
            clearTimeout(this.updateStateTimeout_);
            this.updateStateTimeout_ = null;
        }
        this.tracker_.removeAll();
        Store.getInstance().removeObserver(this);
    }
    onQueryParamsChanged_(newParams) {
        const searchTerm = newParams.get('q') || '';
        let selectedId = newParams.get('id');
        if (!selectedId && !searchTerm) {
            selectedId = this.defaultId_;
        }
        if (searchTerm !== this.searchTerm_) {
            this.searchTerm_ = searchTerm;
            Store.getInstance().dispatch(setSearchTerm(searchTerm));
        }
        if (selectedId && selectedId !== this.selectedId_) {
            this.selectedId_ = selectedId;
            // Need to dispatch a deferred action so that during page load
            // `Store.getInstance().data` will only evaluate after the Store is
            // initialized.
            Store.getInstance().dispatchAsync((dispatch) => {
                dispatch(selectFolder(selectedId, Store.getInstance().data.nodes));
            });
        }
    }
    onStateChanged(state) {
        this.selectedId_ = state.selectedFolder;
        this.searchTerm_ = state.search.term;
        // Default to the first child of root, which could be
        // ACCOUNT_HEADING_NODE_ID, the local bookmark bar, or the account bookmark
        // bar.
        this.defaultId_ = state.nodes[ROOT_NODE_ID].children[0];
        if (this.updateStateTimeout_) {
            clearTimeout(this.updateStateTimeout_);
        }
        // Debounce to microtask timing.
        this.updateStateTimeout_ = setTimeout(() => this.updateQueryParams_(), 0);
    }
    updateQueryParams_() {
        assert(this.updateStateTimeout_);
        clearTimeout(this.updateStateTimeout_);
        this.updateStateTimeout_ = null;
        const queryParams = new URLSearchParams();
        if (this.searchTerm_) {
            queryParams.set('q', this.searchTerm_);
        }
        else if (this.selectedId_ !== this.defaultId_) {
            queryParams.set('id', this.selectedId_);
        }
        CrRouter.getInstance().setQueryParams(queryParams);
    }
}
