package run.halo.app.extension.index;

import org.springframework.lang.NonNull;
import run.halo.app.extension.Extension;
import run.halo.app.extension.ExtensionStoreUtil;
import run.halo.app.extension.GroupVersionKind;
import run.halo.app.extension.Scheme;
import run.halo.app.extension.SchemeManager;

/**
 * <p>{@link IndexerFactory} is used to create {@link Indexer} for {@link Extension} type.</p>
 * <p>It's stored {@link Indexer} by key space, the key space is generated by {@link Scheme} like
 * {@link ExtensionStoreUtil#buildStoreNamePrefix(Scheme)}.</p>
 * <p>E.g. create {@link Indexer} for Post extension, the mapping relationship is:</p>
 * <pre>
 *    /registry/content.halo.run/posts -> Indexer
 * </pre>
 *
 * @author guqing
 * @since 2.12.0
 */
public interface IndexerFactory {

    /**
     * Create {@link Indexer} for {@link Extension} type.
     *
     * @param extensionType the extension type must exist in {@link SchemeManager}.
     * @param extensionIterator the extension iterator to iterate all records for the extension type
     * @return created {@link Indexer}
     */
    @NonNull
    Indexer createIndexerFor(Class<? extends Extension> extensionType,
        ExtensionIterator<? extends Extension> extensionIterator);

    /**
     * Get {@link Indexer} for {@link GroupVersionKind}.
     *
     * @param gvk the group version kind must exist in {@link SchemeManager}
     * @return the indexer
     * @throws IllegalArgumentException if the {@link GroupVersionKind} represents a special
     *                                  {@link Extension} not exists in {@link SchemeManager}
     */
    @NonNull
    Indexer getIndexer(GroupVersionKind gvk);

    boolean contains(GroupVersionKind gvk);

    /**
     * <p>Remove a specific {@link Indexer} by {@link Scheme} that represents a {@link Extension}
     * .</p>
     * <p>Usually, the specified {@link Scheme} is not in {@link SchemeManager} at this time.</p>
     *
     * @param scheme the scheme represents a {@link Extension}
     */
    void removeIndexer(Scheme scheme);
}
