class TrieNode {
    constructor() {
        this.children = {};
        this.isEndOfWord = false;
        this.data = null;
    }
}
 
class PortSearch {
    constructor() {
        this.root = new TrieNode();
    }
 
    insert(word, data) {
        let node = this.root;
        for (let char of word) {
            if (!node.children[char]) {
                node.children[char] = new TrieNode();
            }
            node = node.children[char];
        }
        node.isEndOfWord = true;
        node.data = data;
    }
 
    search(textToSearch) {
        let results = [];
        let node = this.root;
        for (let char of textToSearch) {
            if (node.children[char]) {
                node = node.children[char];
            } else {
                break;
            }
        }
 
        if (node.isEndOfWord) {
            results.push(node.data);
        }
 
        return results;
    }
}
 
function createTypeahead(textToSearch, portList) {
    const portSearch = new PortSearch();
 
    // Insert each port's name into the trie
    for (let port of portList) {
        portSearch.insert(port.name.toLowerCase(), port);
    }
 
    // Search for the text in the trie
    const results = portSearch.search(textToSearch.toLowerCase());
 
    return results;
}
 
// Example usage:
const portList = [
    { locode: "EGSCN", name: "Suez Canal", id: "EGSCN-4821" },
];
 
const textToSearch = "nal";
const matchingPorts = createTypeahead(textToSearch, portList);
console.log(matchingPorts);
 
import java.util.HashMap;
import java.util.Map;
 
class TrieNode {
    Map<Character, TrieNode> children;
    boolean isEndOfWord;
    Object data;
 
    TrieNode() {
        this.children = new HashMap<>();
        this.isEndOfWord = false;
        this.data = null;
    }
}
 
class PortSearch {
    TrieNode root;
 
    PortSearch() {
        this.root = new TrieNode();
    }
 
    void insert(String word, Object data) {
        TrieNode node = this.root;
        for (char c : word.toCharArray()) {
            if (!node.children.containsKey(c)) {
                node.children.put(c, new TrieNode());
            }
            node = node.children.get(c);
        }
        node.isEndOfWord = true;
        node.data = data;
    }
 
    Object search(String textToSearch) {
        TrieNode node = this.root;
        for (char c : textToSearch.toCharArray()) {
            if (node.children.containsKey(c)) {
                node = node.children.get(c);
            } else {
                break;
            }
        }
 
        return (node.isEndOfWord) ? node.data : null;
    }
}
 
public class TypeaheadSearch {
    public static Object createTypeahead(String textToSearch, Iterable<Map<String, Object>> portList) {
        PortSearch portSearch = new PortSearch();
 
        // Insert each port's name into the trie
        for (Map<String, Object> port : portList) {
            portSearch.insert(((String) port.get("name")).toLowerCase(), port);
        }
 
        // Search for the text in the trie
        return portSearch.search(textToSearch.toLowerCase());
    }
 
    public static void main(String[] args) {
        Iterable<Map<String, Object>> portList = List.of(
                Map.of("locode", "EGSCN", "name", "Suez Canal", "id", "EGSCN-4821")
        );
 
        String textToSearch = "nal";
        Object matchingPort = createTypeahead(textToSearch, portList);
        System.out.println(matchingPort);
    }
}