// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

package com.azure.search.documents.indexes.models;

import com.azure.core.annotation.Fluent;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/** Represents an indexer. */
@Fluent
public final class SearchIndexer implements JsonSerializable<SearchIndexer> {
    /*
     * The name of the indexer.
     */
    private final String name;

    /*
     * The description of the indexer.
     */
    private String description;

    /*
     * The name of the datasource from which this indexer reads data.
     */
    private String dataSourceName;

    /*
     * The name of the skillset executing with this indexer.
     */
    private String skillsetName;

    /*
     * The name of the index to which this indexer writes data.
     */
    private String targetIndexName;

    /*
     * The schedule for this indexer.
     */
    private IndexingSchedule schedule;

    /*
     * Parameters for indexer execution.
     */
    private IndexingParameters parameters;

    /*
     * Defines mappings between fields in the data source and corresponding target fields in the index.
     */
    private List<FieldMapping> fieldMappings;

    /*
     * Output field mappings are applied after enrichment and immediately before indexing.
     */
    private List<FieldMapping> outputFieldMappings;

    /*
     * A value indicating whether the indexer is disabled. Default is false.
     */
    private Boolean isDisabled;

    /*
     * The ETag of the indexer.
     */
    private String eTag;

    /*
     * A description of an encryption key that you create in Azure Key Vault. This key is used to provide an additional
     * level of encryption-at-rest for your indexer definition (as well as indexer execution status) when you want full
     * assurance that no one, not even Microsoft, can decrypt them in Azure Cognitive Search. Once you have encrypted
     * your indexer definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set
     * this property to null. You can change this property as needed if you want to rotate your encryption key; Your
     * indexer definition (and indexer execution status) will be unaffected. Encryption with customer-managed keys is
     * not available for free search services, and is only available for paid services created on or after January 1,
     * 2019.
     */
    private SearchResourceEncryptionKey encryptionKey;

    /*
     * Adds caching to an enrichment pipeline to allow for incremental modification steps without having to rebuild the
     * index every time.
     */
    private SearchIndexerCache cache;

    /**
     * Creates an instance of SearchIndexer class.
     *
     * @param name the name value to set.
     */
    public SearchIndexer(String name) {
        this.name = name;
    }

    /**
     * Constructor of {@link SearchIndexer}.
     *
     * @param name The name of the indexer.
     * @param dataSourceName The name of the datasource from which this indexer reads data.
     * @param targetIndexName The name of the index to which this indexer writes data.
     */
    public SearchIndexer(String name, String dataSourceName, String targetIndexName) {
        this.name = name;
        this.dataSourceName = dataSourceName;
        this.targetIndexName = targetIndexName;
    }

    /**
     * Get the name property: The name of the indexer.
     *
     * @return the name value.
     */
    public String getName() {
        return this.name;
    }

    /**
     * Get the description property: The description of the indexer.
     *
     * @return the description value.
     */
    public String getDescription() {
        return this.description;
    }

    /**
     * Set the description property: The description of the indexer.
     *
     * @param description the description value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setDescription(String description) {
        this.description = description;
        return this;
    }

    /**
     * Get the dataSourceName property: The name of the datasource from which this indexer reads data.
     *
     * @return the dataSourceName value.
     */
    public String getDataSourceName() {
        return this.dataSourceName;
    }

    /**
     * Set the dataSourceName property: The name of the datasource from which this indexer reads data.
     *
     * @param dataSourceName the dataSourceName value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setDataSourceName(String dataSourceName) {
        this.dataSourceName = dataSourceName;
        return this;
    }

    /**
     * Get the skillsetName property: The name of the skillset executing with this indexer.
     *
     * @return the skillsetName value.
     */
    public String getSkillsetName() {
        return this.skillsetName;
    }

    /**
     * Set the skillsetName property: The name of the skillset executing with this indexer.
     *
     * @param skillsetName the skillsetName value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setSkillsetName(String skillsetName) {
        this.skillsetName = skillsetName;
        return this;
    }

    /**
     * Get the targetIndexName property: The name of the index to which this indexer writes data.
     *
     * @return the targetIndexName value.
     */
    public String getTargetIndexName() {
        return this.targetIndexName;
    }

    /**
     * Set the targetIndexName property: The name of the index to which this indexer writes data.
     *
     * @param targetIndexName the targetIndexName value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setTargetIndexName(String targetIndexName) {
        this.targetIndexName = targetIndexName;
        return this;
    }

    /**
     * Get the schedule property: The schedule for this indexer.
     *
     * @return the schedule value.
     */
    public IndexingSchedule getSchedule() {
        return this.schedule;
    }

    /**
     * Set the schedule property: The schedule for this indexer.
     *
     * @param schedule the schedule value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setSchedule(IndexingSchedule schedule) {
        this.schedule = schedule;
        return this;
    }

    /**
     * Get the parameters property: Parameters for indexer execution.
     *
     * @return the parameters value.
     */
    public IndexingParameters getParameters() {
        return this.parameters;
    }

    /**
     * Set the parameters property: Parameters for indexer execution.
     *
     * @param parameters the parameters value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setParameters(IndexingParameters parameters) {
        this.parameters = parameters;
        return this;
    }

    /**
     * Get the fieldMappings property: Defines mappings between fields in the data source and corresponding target
     * fields in the index.
     *
     * @return the fieldMappings value.
     */
    public List<FieldMapping> getFieldMappings() {
        return this.fieldMappings;
    }

    /**
     * Set the fieldMappings property: Defines mappings between fields in the data source and corresponding target
     * fields in the index.
     *
     * @param fieldMappings the fieldMappings value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setFieldMappings(List<FieldMapping> fieldMappings) {
        this.fieldMappings = fieldMappings;
        return this;
    }

    /**
     * Get the outputFieldMappings property: Output field mappings are applied after enrichment and immediately before
     * indexing.
     *
     * @return the outputFieldMappings value.
     */
    public List<FieldMapping> getOutputFieldMappings() {
        return this.outputFieldMappings;
    }

    /**
     * Set the outputFieldMappings property: Output field mappings are applied after enrichment and immediately before
     * indexing.
     *
     * @param outputFieldMappings the outputFieldMappings value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setOutputFieldMappings(List<FieldMapping> outputFieldMappings) {
        this.outputFieldMappings = outputFieldMappings;
        return this;
    }

    /**
     * Get the isDisabled property: A value indicating whether the indexer is disabled. Default is false.
     *
     * @return the isDisabled value.
     */
    public Boolean isDisabled() {
        return this.isDisabled;
    }

    /**
     * Set the isDisabled property: A value indicating whether the indexer is disabled. Default is false.
     *
     * @param isDisabled the isDisabled value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setIsDisabled(Boolean isDisabled) {
        this.isDisabled = isDisabled;
        return this;
    }

    /**
     * Get the eTag property: The ETag of the indexer.
     *
     * @return the eTag value.
     */
    public String getETag() {
        return this.eTag;
    }

    /**
     * Set the eTag property: The ETag of the indexer.
     *
     * @param eTag the eTag value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setETag(String eTag) {
        this.eTag = eTag;
        return this;
    }

    /**
     * Get the encryptionKey property: A description of an encryption key that you create in Azure Key Vault. This key
     * is used to provide an additional level of encryption-at-rest for your indexer definition (as well as indexer
     * execution status) when you want full assurance that no one, not even Microsoft, can decrypt them in Azure
     * Cognitive Search. Once you have encrypted your indexer definition, it will always remain encrypted. Azure
     * Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you
     * want to rotate your encryption key; Your indexer definition (and indexer execution status) will be unaffected.
     * Encryption with customer-managed keys is not available for free search services, and is only available for paid
     * services created on or after January 1, 2019.
     *
     * @return the encryptionKey value.
     */
    public SearchResourceEncryptionKey getEncryptionKey() {
        return this.encryptionKey;
    }

    /**
     * Set the encryptionKey property: A description of an encryption key that you create in Azure Key Vault. This key
     * is used to provide an additional level of encryption-at-rest for your indexer definition (as well as indexer
     * execution status) when you want full assurance that no one, not even Microsoft, can decrypt them in Azure
     * Cognitive Search. Once you have encrypted your indexer definition, it will always remain encrypted. Azure
     * Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you
     * want to rotate your encryption key; Your indexer definition (and indexer execution status) will be unaffected.
     * Encryption with customer-managed keys is not available for free search services, and is only available for paid
     * services created on or after January 1, 2019.
     *
     * @param encryptionKey the encryptionKey value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setEncryptionKey(SearchResourceEncryptionKey encryptionKey) {
        this.encryptionKey = encryptionKey;
        return this;
    }

    /**
     * Get the cache property: Adds caching to an enrichment pipeline to allow for incremental modification steps
     * without having to rebuild the index every time.
     *
     * @return the cache value.
     */
    public SearchIndexerCache getCache() {
        return this.cache;
    }

    /**
     * Set the cache property: Adds caching to an enrichment pipeline to allow for incremental modification steps
     * without having to rebuild the index every time.
     *
     * @param cache the cache value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setCache(SearchIndexerCache cache) {
        this.cache = cache;
        return this;
    }

    @Override
    public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
        jsonWriter.writeStartObject();
        jsonWriter.writeStringField("name", this.name);
        jsonWriter.writeStringField("description", this.description);
        jsonWriter.writeStringField("dataSourceName", this.dataSourceName);
        jsonWriter.writeStringField("skillsetName", this.skillsetName);
        jsonWriter.writeStringField("targetIndexName", this.targetIndexName);
        jsonWriter.writeJsonField("schedule", this.schedule);
        jsonWriter.writeJsonField("parameters", this.parameters);
        jsonWriter.writeArrayField("fieldMappings", this.fieldMappings, (writer, element) -> writer.writeJson(element));
        jsonWriter.writeArrayField(
                "outputFieldMappings", this.outputFieldMappings, (writer, element) -> writer.writeJson(element));
        jsonWriter.writeBooleanField("disabled", this.isDisabled);
        jsonWriter.writeStringField("@odata.etag", this.eTag);
        jsonWriter.writeJsonField("encryptionKey", this.encryptionKey);
        jsonWriter.writeJsonField("cache", this.cache);
        return jsonWriter.writeEndObject();
    }

    /**
     * Reads an instance of SearchIndexer from the JsonReader.
     *
     * @param jsonReader The JsonReader being read.
     * @return An instance of SearchIndexer if the JsonReader was pointing to an instance of it, or null if it was
     *     pointing to JSON null.
     * @throws IllegalStateException If the deserialized JSON object was missing any required properties.
     * @throws IOException If an error occurs while reading the SearchIndexer.
     */
    public static SearchIndexer fromJson(JsonReader jsonReader) throws IOException {
        return jsonReader.readObject(
                reader -> {
                    boolean nameFound = false;
                    String name = null;
                    String description = null;
                    String dataSourceName = null;
                    String skillsetName = null;
                    String targetIndexName = null;
                    IndexingSchedule schedule = null;
                    IndexingParameters parameters = null;
                    List<FieldMapping> fieldMappings = null;
                    List<FieldMapping> outputFieldMappings = null;
                    Boolean isDisabled = null;
                    String eTag = null;
                    SearchResourceEncryptionKey encryptionKey = null;
                    SearchIndexerCache cache = null;
                    while (reader.nextToken() != JsonToken.END_OBJECT) {
                        String fieldName = reader.getFieldName();
                        reader.nextToken();

                        if ("name".equals(fieldName)) {
                            name = reader.getString();
                            nameFound = true;
                        } else if ("description".equals(fieldName)) {
                            description = reader.getString();
                        } else if ("dataSourceName".equals(fieldName)) {
                            dataSourceName = reader.getString();
                        } else if ("skillsetName".equals(fieldName)) {
                            skillsetName = reader.getString();
                        } else if ("targetIndexName".equals(fieldName)) {
                            targetIndexName = reader.getString();
                        } else if ("schedule".equals(fieldName)) {
                            schedule = IndexingSchedule.fromJson(reader);
                        } else if ("parameters".equals(fieldName)) {
                            parameters = IndexingParameters.fromJson(reader);
                        } else if ("fieldMappings".equals(fieldName)) {
                            fieldMappings = reader.readArray(reader1 -> FieldMapping.fromJson(reader1));
                        } else if ("outputFieldMappings".equals(fieldName)) {
                            outputFieldMappings = reader.readArray(reader1 -> FieldMapping.fromJson(reader1));
                        } else if ("disabled".equals(fieldName)) {
                            isDisabled = reader.getNullable(JsonReader::getBoolean);
                        } else if ("@odata.etag".equals(fieldName)) {
                            eTag = reader.getString();
                        } else if ("encryptionKey".equals(fieldName)) {
                            encryptionKey = SearchResourceEncryptionKey.fromJson(reader);
                        } else if ("cache".equals(fieldName)) {
                            cache = SearchIndexerCache.fromJson(reader);
                        } else {
                            reader.skipChildren();
                        }
                    }
                    if (nameFound) {
                        SearchIndexer deserializedSearchIndexer = new SearchIndexer(name);
                        deserializedSearchIndexer.description = description;
                        deserializedSearchIndexer.dataSourceName = dataSourceName;
                        deserializedSearchIndexer.skillsetName = skillsetName;
                        deserializedSearchIndexer.targetIndexName = targetIndexName;
                        deserializedSearchIndexer.schedule = schedule;
                        deserializedSearchIndexer.parameters = parameters;
                        deserializedSearchIndexer.fieldMappings = fieldMappings;
                        deserializedSearchIndexer.outputFieldMappings = outputFieldMappings;
                        deserializedSearchIndexer.isDisabled = isDisabled;
                        deserializedSearchIndexer.eTag = eTag;
                        deserializedSearchIndexer.encryptionKey = encryptionKey;
                        deserializedSearchIndexer.cache = cache;

                        return deserializedSearchIndexer;
                    }
                    List<String> missingProperties = new ArrayList<>();
                    if (!nameFound) {
                        missingProperties.add("name");
                    }

                    throw new IllegalStateException(
                            "Missing required property/properties: " + String.join(", ", missingProperties));
                });
    }

    /**
     * Set the fieldMappings property: Defines mappings between fields in the data source and corresponding target
     * fields in the index.
     *
     * @param fieldMappings the fieldMappings value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setFieldMappings(FieldMapping... fieldMappings) {
        this.fieldMappings = (fieldMappings == null) ? null : java.util.Arrays.asList(fieldMappings);
        return this;
    }

    /**
     * Set the outputFieldMappings property: Output field mappings are applied after enrichment and immediately before
     * indexing.
     *
     * @param outputFieldMappings the outputFieldMappings value to set.
     * @return the SearchIndexer object itself.
     */
    public SearchIndexer setOutputFieldMappings(FieldMapping... outputFieldMappings) {
        this.outputFieldMappings = (outputFieldMappings == null) ? null : java.util.Arrays.asList(outputFieldMappings);
        return this;
    }
}
