import CloseIcon from 'mdi-react/CloseIcon';
import * as React from 'react';
import { fromEvent, Subscription } from 'rxjs';
import stringScore from 'string-score';
import { VirtualList } from '../../components/VirtualList';
import { ExampleSearch } from './ExampleSearch';
import exampleSearches from './exampleSearchesData';
const numShownStep = 6;
const calcScore = (description, term) => {
    if (term.trim() === '') {
        return 1;
    }
    const notAlphanumeric = /[^A-Za-z0-9]/;
    const descWords = description.split(notAlphanumeric);
    const termWords = term.split(notAlphanumeric);
    let score = 0;
    let count = 0;
    for (const dWord of descWords) {
        for (const tWord of termWords) {
            const s = stringScore(dWord, tWord);
            if (isNaN(s)) {
                continue; // e.g. empty string
            }
            count++;
            score += s;
        }
    }
    if (count > 0) {
        score = score / count; // average, so that we keep a normalized score value
    }
    return score;
};
const getSortedExampleSearches = (filterTerm) => {
    // Calculate scores against our filter term.
    const scoredSearches = exampleSearches.map((search, index) => ({
        search,
        index,
        score: calcScore(search.description, filterTerm),
    }));
    // Sort searches based on calculate score.
    scoredSearches.sort((a, b) => {
        if (a.score === b.score) {
            return 0;
        }
        return a.score > b.score ? -1 : 1;
    });
    return scoredSearches;
};
export class ExampleSearches extends React.Component {
    constructor() {
        super(...arguments);
        this.state = { filterTerm: '', numShown: numShownStep, scoredSearches: getSortedExampleSearches('') };
        this.listNode = null;
        this.subscriptions = new Subscription();
        this.handleFilterChange = event => {
            this.setState({
                filterTerm: event.currentTarget.value,
                scoredSearches: getSortedExampleSearches(event.currentTarget.value),
            });
        };
        this.handleShowMore = () => {
            this.setState(state => ({
                numShown: Math.min(state.numShown + numShownStep, this.state.scoredSearches.length),
            }));
        };
    }
    componentDidMount() {
        if (this.listNode) {
            this.subscriptions.add(fromEvent(this.listNode, 'wheel').subscribe((e) => {
                const div = e.currentTarget;
                if ((e.deltaY > 0 && div.scrollTop >= div.scrollHeight - div.clientHeight) ||
                    (e.deltaY < 0 && div.scrollTop === 0)) {
                    e.preventDefault();
                }
            }));
        }
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        return (React.createElement("div", { className: "example-searches" },
            React.createElement("div", { className: "example-searches__filter-box" },
                React.createElement("div", { className: "example-searches__flex-row" },
                    React.createElement("h2", { className: "example-searches__title" }, "Built-in saved searches"),
                    React.createElement("button", { className: "btn btn-icon", onClick: this.props.onClose },
                        React.createElement(CloseIcon, { className: "icon-inline" }))),
                React.createElement("p", null, "To edit or subscribe to a built-in saved search, save it first."),
                React.createElement("input", { type: "text", className: "form-control", placeholder: "Filter...", value: this.state.filterTerm, onChange: this.handleFilterChange })),
            React.createElement("div", { className: "example-searches__examples", ref: ref => {
                    this.listNode = ref;
                } },
                React.createElement(VirtualList, { itemsToShow: this.state.numShown, onShowMoreItems: this.handleShowMore, items: this.state.scoredSearches.map(({ search, index, score }) => (React.createElement(ExampleSearch, { key: `${index}`, search: search, isLightTheme: this.props.isLightTheme, onSave: this.props.onExampleSelected, 
                        // We just want to hide the items that don't match the filter so that
                        // we do not hit the search endpoint every time the filter term changes
                        // and mounts and remounts the same queries to get the sparkline data
                        isHidden: score < 0.01 }))) }))));
    }
}
//# sourceMappingURL=ExampleSearches.js.map