/*
 * Copyright 2013-2021 the original author or authors.
 *
 * Licensed 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
 *
 *      https://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.springframework.cloud.sleuth.zipkin2;

import zipkin2.codec.SpanBytesEncoder;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * Zipkin settings.
 *
 * @author Spencer Gibb
 * @since 1.0.0
 */
@ConfigurationProperties("spring.zipkin")
// public as the senders that use this are in another package
public class ZipkinProperties {

	/**
	 * URL of the zipkin query server instance. You can also provide the service id of the
	 * Zipkin server if Zipkin's registered in service discovery (e.g.
	 * https://zipkinserver/).
	 */
	private String baseUrl = "http://localhost:9411/";

	/**
	 * The API path to append to baseUrl (above) as suffix. This applies if you use other
	 * monitoring tools, such as New Relic. The trace API doesn't need the API path, so
	 * you can set it to blank ("") in the configuration.
	 */
	private String apiPath = null;

	/**
	 * If set to {@code false}, will treat the {@link ZipkinProperties#baseUrl} as a URL
	 * always.
	 */
	private Boolean discoveryClientEnabled;

	/**
	 * Enables sending spans to Zipkin.
	 */
	private boolean enabled = true;

	/**
	 * Timeout in millis for the check for Zipkin availability.
	 */
	private int checkTimeout = 1_000;

	/**
	 * Timeout in seconds before pending spans will be sent in batches to Zipkin.
	 */
	private int messageTimeout = 1;

	/**
	 * Encoding type of spans sent to Zipkin. Set to {@link SpanBytesEncoder#JSON_V1} if
	 * your server is not recent.
	 */
	private SpanBytesEncoder encoder = SpanBytesEncoder.JSON_V2;

	/**
	 * Configuration related to compressions of spans sent to Zipkin.
	 */
	private Compression compression = new Compression();

	private Service service = new Service();

	private Locator locator = new Locator();

	/**
	 * Maximum backlog of spans reported vs sent.
	 */
	private int queuedMaxSpans = 1000;

	public Locator getLocator() {
		return this.locator;
	}

	public void setLocator(Locator locator) {
		this.locator = locator;
	}

	public String getBaseUrl() {
		return this.baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	public String getApiPath() {
		return this.apiPath;
	}

	public void setApiPath(String apiPath) {
		this.apiPath = apiPath;
	}

	public boolean isEnabled() {
		return this.enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public Boolean getDiscoveryClientEnabled() {
		return this.discoveryClientEnabled;
	}

	public void setDiscoveryClientEnabled(Boolean discoveryClientEnabled) {
		this.discoveryClientEnabled = discoveryClientEnabled;
	}

	public int getMessageTimeout() {
		return this.messageTimeout;
	}

	public void setMessageTimeout(int messageTimeout) {
		this.messageTimeout = messageTimeout;
	}

	public int getCheckTimeout() {
		return this.checkTimeout;
	}

	public void setCheckTimeout(int checkTimeout) {
		this.checkTimeout = checkTimeout;
	}

	public Compression getCompression() {
		return this.compression;
	}

	public void setCompression(Compression compression) {
		this.compression = compression;
	}

	public Service getService() {
		return this.service;
	}

	public void setService(Service service) {
		this.service = service;
	}

	public SpanBytesEncoder getEncoder() {
		return this.encoder;
	}

	public void setEncoder(SpanBytesEncoder encoder) {
		this.encoder = encoder;
	}

	public int getQueuedMaxSpans() {
		return queuedMaxSpans;
	}

	public void setQueuedMaxSpans(int queuedMaxSpans) {
		this.queuedMaxSpans = queuedMaxSpans;
	}

	/** When enabled, spans are gzipped before sent to the zipkin server. */
	public static class Compression {

		private boolean enabled = false;

		public boolean isEnabled() {
			return this.enabled;
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}

	}

	/**
	 * When set will override the default {@code spring.application.name} value of the
	 * service id.
	 */
	public static class Service {

		/**
		 * The name of the service, from which the Span was sent via HTTP, that should
		 * appear in Zipkin.
		 */
		private String name;

		public String getName() {
			return this.name;
		}

		public void setName(String name) {
			this.name = name;
		}

	}

	/**
	 * Configuration related to locating of the host name from service discovery. This
	 * property is NOT related to finding Zipkin via Service Disovery. To do so use the
	 * {@link ZipkinProperties#baseUrl} property with the service name set inside the URL.
	 */
	public static class Locator {

		private Discovery discovery;

		public Discovery getDiscovery() {
			return this.discovery;
		}

		public void setDiscovery(Discovery discovery) {
			this.discovery = discovery;
		}

		/**
		 * Discovery Locator properties.
		 */
		public static class Discovery {

			/** Enabling of locating the host name via service discovery. */
			private boolean enabled;

			public boolean isEnabled() {
				return this.enabled;
			}

			public void setEnabled(boolean enabled) {
				this.enabled = enabled;
			}

		}

	}

}
