/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.nlpcraft.model;

import java.io.*;
import java.util.*;

/**
 * Data model element.
 * <p>
 * Data model element defines a named entity that will be detected in the user input. A model element
 * typically is one or more individual words that have a consistent semantic meaning and typically denote
 * a real-world object, such as persons, locations, number, date and time, organizations, products, etc.
 * Such object can be abstract or have a physical existence.
 * <p>
 * Read full documentation in <a target=_ href="https://nlpcraft.apache.org/data-model.html">Data Model</a> section and review
 * <a target=_ href="https://github.com/apache/incubator-nlpcraft/tree/master/nlpcraft-examples">examples</a>.
 *
 * @see NCCustomParser
 */
public interface NCElement extends NCMetadata, Serializable {
    /**
     * Gets unique ID of this element.
     * <p>
     * This unique ID should be human-readable for simpler debugging and testing of the model.
     * Although element ID could be any arbitrary string it is highly recommended having
     * element ID as a lower case string starting with some model prefix, followed by colon and
     * then the element's name. For example, some built-in NLPCraft IDs are: <code>nlpcraft:date</code>,
     * <code>nlpcraft:city</code>.
     * <p>
     * Few important notes:
     * <ul>
     *      <li>Element IDs starting with <code>nlpcraft:</code> are reserved for built-in NLPCraft IDs.</li>
     *      <li>
     *          Element ID is an implicit synonym for that element.
     *          Thus element ID can be used in the user input directly to clearly
     *          disambiguate the element in the input sentence instead of relying on synonyms or other
     *          ways of detection.
     *      </li>
     * </ul>
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>id</code> property:
     * <pre class="brush: js, highlight: [3]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @see NCToken#getId()
     * @return Unique ID of this element.
     */
    String getId();

    /**
     * Gets the list of groups this element belongs to.
     * <p>
     * Model element can belong to one or more groups. By default, the element belongs to a single group whose group
     * ID is equal to its {@link #getId() ID}. The proper grouping of the model elements is required for operation
     * of Short-Term-Memory (STM) in {@link NCConversation conversation} (if and when conversation
     * is used). Specifically, a token (i.e. found model element) that is part of the group set will override
     * other tokens from the same set or its superset. In other words, tokens with a smaller group set
     * (more specific token) will override the tokens from a larger group set (more generic tokens).
     * <p>
     * Note that built-in tokens (including from 3rd party token providers) belong to a single group whose group
     * ID is equal to their IDs.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>groups</code> property:
     * <pre class="brush: js, highlight: [5]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "groups": ["group1", "group2"]
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @return List of groups this element belongs to. By default, the model element belongs to one group
     *      with ID equal to the element {@link #getId() ID}.
     * @see NCConversation
     * @see #getId() 
     */
    default List<String> getGroups() {
        return Collections.singletonList(getId());
    }

    /**
     * Shortcut method to test if this element is a member of given group. It is equivalent to:
     * <pre class="brush: java">
     *     return getGroups().contains(grp);
     * </pre>
     *
     * @param grp Token group to test.
     * @return {@code True} if this element belongs to the given group, {@code false} otherwise.
     */
    default boolean isMemberOf(String grp) {
        return getGroups().contains(grp);
    }

    /**
     * Gets optional user-defined element's metadata. When a {@link NCToken token} for this element
     * is detected in the input this metadata is merged into {@link NCToken#getMetadata()} method returned metadata.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>description</code> property:
     * <pre class="brush: js, highlight: [8,9,10,11,12]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ],
     *             "metadata": {
     *                 "str": "val1",
     *                 "num": 100,
     *                 "bool": false
     *             }
     *         }
     *     ]
     * </pre>
     *
     * @return Element's metadata or empty collection if none provided. Default implementation return empty collection.
     */
    default Map<String, Object> getMetadata() {
        return Collections.emptyMap();
    }

    /**
     * Gets optional element description.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>description</code> property:
     * <pre class="brush: js, highlight: [4]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @return Optional element description. Default implementation returns {@code null}.
     */
    default String getDescription() {
        return null;
    }

    /**
     * Gets optional map of {@link NCValue values} for this element.
     * <p>
     * Each element can generally be recognized either by one of its synonyms or values. Elements and their values
     * are analogous to types and instances of that type in programming languages. Each value
     * has a name and optional set of its own synonyms by which that value, and ultimately its element, can be
     * recognized by. Note that value name itself acts as an implicit synonym even when no additional synonyms added
     * for that value.
     * <p>
     * Consider this example. A model element {@code x:car} can have:
     * <ul>
     *      <li>
     *          Set of general synonyms:
     *          <code>{transportation|transport|_} {vehicle|car|sedan|auto|automobile|suv|crossover|coupe|truck}</code>
     *      </li>
     *      <li>Set of values:
     *          <ul>
     *              <li>{@code mercedes} with synonyms {@code (mercedes, mercedes-benz, mb, benz)}</li>
     *              <li>{@code bmw} with synonyms {@code (bmw, bimmer)}</li>
     *              <li>{@code chevrolet} with synonyms {@code (chevy, chevrolet)}</li>
     *          </ul>
     *      </li>
     * </ul>
     * With that setup {@code x:car} element will be recognized by any of the following input sub-string:
     * <ul>
     *      <li>{@code transport car}</li>
     *      <li>{@code benz}</li>
     *      <li>{@code automobile}</li>
     *      <li>{@code transport vehicle}</li>
     *      <li>{@code sedan}</li>
     *      <li>{@code chevy}</li>
     *      <li>{@code bimmer}</li>
     *      <li>{@code x:car}</li>
     * </ul>
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>values</code> property:
     * <pre class="brush: js, highlight: [8,9,10,11,12,13]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ],
     *             "values": [
     *                  {
     *                      "name": "name1",
     *                      "synonyms": ["syn1", "syn2"]
     *                  }
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @return Map of value's name and its synonyms or {@code null} if not defined.
     */
    default List<NCValue> getValues() {
        return Collections.emptyList();
    }

    /**
     * Gets optional ID of the immediate parent element. Parent ID allows model elements to form into hierarchy.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>parentId</code> property:
     * <pre class="brush: js, highlight: [5]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "parentId": "parent",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @return Optional parent element ID, or {@code null} if not specified. Default implementation returns
     *      {@code null}.
     */
    default String getParentId() {
        return null;
    }

    /**
     * Gets the list of synonyms by which this model element will be recognized by. Read more about
     * many forms of synonyms in <a target=_ href="https://nlpcraft.apache.org/data-model.html">Data Model</a> section
     * and review <a target=_ href="https://github.com/apache/incubator-nlpcraft/tree/master/nlpcraft-examples">examples</a>.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>synonyms</code> property:
     * <pre class="brush: js, highlight: [5,6,7]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ]
     *         }
     *     ]
     * </pre>
     *
     * @return List of synonyms for this element. List is generally optional since element's ID acts
     *      as an implicit synonym. Default implementation returns an empty list.
     */
    default List<String> getSynonyms() {
        return Collections.emptyList();
    }

    /**
     * Gets optional dynamic value loader. This loader will be used additionally to any
     * values defined in {@link #getValues()} method. Default implementation returns {@code null}.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>valueLoader</code> property with value
     * of a fully qualified class name implementing {@link NCValueLoader} interface. Note that
     * only one instance of the value loader will be created per model and given class name:
     * <pre class="brush: js, highlight: [14]">
     *     "elements": [
     *         {
     *             "id": "phone:act",
     *             "description": "Phone action.",
     *             "synonyms": [
     *                 "{give|_} {call|phone|ring|dial|dial up|ping|contact}"
     *             ],
     *             "values": [
     *                  {
     *                      "name": "name1",
     *                      "synonyms": ["syn1", "syn2"]
     *                  }
     *             ],
     *             "valueLoader": "my.package.ValueLoader"
     *         }
     *     ]
     * </pre>
     *
     * @return Optional instance of dynamic value loader.
     */
    default Optional<NCValueLoader> getValueLoader() {
        return Optional.empty();
    }

    /**
     * Whether to permutate multi-word synonyms. Automatic multi-word synonyms permutations greatly
     * increase the total number of synonyms in the system and allows for better multi-word synonym detection.
     * For example, if permutation is allowed the synonym "a b c" will be automatically converted into a
     * sequence of synonyms of "a b c", "b a c", "a c b".
     * <p>
     * This property overrides the value from {@link NCModelView#isPermutateSynonyms()}.
     * One should use this property if model's value isn't applicable to this element.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>permutateSynonyms</code>:
     * <pre class="brush: js, highlight: [4]">
     *     "elements": [
     *         {
     *              "id": "elem",
     *              "permutateSynonyms": true,
     *              ...
     *         }
     *     ]
     * </pre>
     *
     * @return Optional synonym permutate property overriding model's one.
     * @see NCModelView#isPermutateSynonyms()
     */
    default Optional<Boolean> isPermutateSynonyms() {
        return Optional.empty();
    }

    /**
     * Whether this element allows the non-stop words gaps in its multi-word synonyms.
     * <p>
     * This property overrides the value from {@link NCModelView#isSparse()}.
     * One should use this property if model's value isn't applicable to this element.
     * <p>
     * <b>JSON</b>
     * <br>
     * If using JSON/YAML model presentation this is set by <code>sparse</code>:
     * <pre class="brush: js, highlight: [4]">
     *     "elements": [
     *         {
     *              "id": "elem",
     *              "sparse": true,
     *              ...
     *         }
     *     ]
     * </pre>
     *
     * @return Optional multi-word synonym sparsity property overriding model's one.
     * @see NCModelView#isSparse()
     */
    default Optional<Boolean> isSparse() {
        return Optional.empty();
    }

    // TODO:
    default Optional<Boolean> isGreedy() {
        return Optional.empty();
    }
}
