import { fromEvent, from } from 'rxjs';
import { map, filter, tap, mergeMap, reduce } from 'rxjs/operators';
let inputElement = document.querySelector('#typeahead-input') as HTMLElement;
let containerElement = document.querySelector('#typeahead-container') as HTMLElement;
let listOfProgrammingLanguages = [
'python', 'javascript', 'java', 'c#', 'c++',
'ruby', 'go', 'swift', 'kotlin', 'php',
'typescript', 'scala', 'shell', 'perl', 'rust',
'r', 'dart', 'elixir', 'clojure', 'lua',
'haskell', 'julia', 'c', 'objective-c', 'groovy',
'assembly', 'coffeescript', 'fortran', 'matlab', 'pascal'
];
fromEvent(inputElement, 'keyup')
.pipe(
// Map each input event to the lowercase value of the input field.
map((event): string => event.target.value.trim().toLowerCase()),
// Clear the container element whenever the input changes.
tap(() => containerElement.innerHTML = ''),
filter(value => value.length > 2),
// For each input value, map it to the filtered list of programming languages.
mergeMap(value =>
from(listOfProgrammingLanguages)
.pipe(
// Filter the programming languages to only those that include the input value.
filter(language => language.includes(value)),
map(language => language.replace(value, `<strong>${value}</strong>`)),
// Accumulate the filtered and highlighted programming languages into an array.
reduce((accumulated: string[], language) => accumulated.concat(language), [])
)
)
)
.subscribe(
// For each accumulated array of filtered and highlighted programming languages,
// update the container element's HTML to display the list.
(filteredLanguages: string[]) => containerElement.innerHTML += `<div>${filteredLanguages.join('<div></div>')}</div>`
);