/*
 * 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.flink.docs.configuration;

import org.apache.flink.configuration.ConfigOption;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.apache.flink.docs.configuration.ConfigOptionsDocGenerator.LOCATIONS;
import static org.apache.flink.docs.configuration.ConfigOptionsDocGenerator.extractConfigOptions;
import static org.apache.flink.docs.configuration.ConfigOptionsDocGenerator.processConfigOptions;
import static org.apache.flink.docs.configuration.ConfigOptionsDocGenerator.stringifyDefault;

/**
 * This test verifies that all {@link ConfigOption ConfigOptions} in the configured
 * {@link ConfigOptionsDocGenerator#LOCATIONS locations} are documented and well-defined (i.e. no 2 options exist for
 * the same key with different descriptions/default values), and that the documentation does not refer to non-existent
 * options.
 */
public class ConfigOptionsDocsCompletenessITCase {

	@Test
	public void testDocsCompleteness() throws IOException, ClassNotFoundException {
		Map<String, DocumentedOption> documentedOptions = parseDocumentedOptions();
		Map<String, ExistingOption> existingOptions = findExistingOptions();

		final Collection<String> problems = new ArrayList<>(0);

		// first check that all existing options are properly documented
		existingOptions.forEach((key, supposedState) -> {
			DocumentedOption documentedState = documentedOptions.remove(key);

			// if nothing matches the docs for this option are up-to-date
			if (documentedState == null) {
				// option is not documented at all
				problems.add("Option " + supposedState.key + " in " + supposedState.containingClass + " is not documented.");
			} else if (!supposedState.defaultValue.equals(documentedState.defaultValue)) {
				// default is outdated
				problems.add("Documented default of " + supposedState.key + " in " + supposedState.containingClass +
					" is outdated. Expected: " + supposedState.defaultValue + " Actual: " + documentedState.defaultValue);
			} else if (!supposedState.description.equals(documentedState.description)) {
				// description is outdated
				problems.add("Documented description of " + supposedState.key + " in " + supposedState.containingClass +
					" is outdated.");
			}
		});

		// documentation contains an option that no longer exists
		if (!documentedOptions.isEmpty()) {
			for (DocumentedOption documentedOption : documentedOptions.values()) {
				problems.add("Documented option " + documentedOption.key + " does not exist.");
			}
		}

		if (!problems.isEmpty()) {
			StringBuilder sb = new StringBuilder("Documentation is outdated, please regenerate it according to the" +
				" instructions in flink-docs/README.md.");
			sb.append(System.lineSeparator());
			sb.append("\tProblems:");
			for (String problem : problems) {
				sb.append(System.lineSeparator());
				sb.append("\t\t");
				sb.append(problem);
			}
			Assert.fail(sb.toString());
		}
	}

	private static Map<String, DocumentedOption> parseDocumentedOptions() throws IOException {
		Path includeFolder = Paths.get(System.getProperty("rootDir"), "docs", "_includes", "generated").toAbsolutePath();
		return Files.list(includeFolder)
			.filter(path -> path.getFileName().toString().contains("configuration"))
			.flatMap(file -> {
				try {
					return parseDocumentedOptionsFromFile(file).stream();
				} catch (IOException ignored) {
					return Stream.empty();
				}
			})
			.collect(Collectors.toMap(option -> option.key, option -> option, (option1, option2) -> {
				if (option1.equals(option2)) {
					// we allow multiple instances of ConfigOptions with the same key if they are identical
					return option1;
				} else {
					// found a ConfigOption pair with the same key that aren't equal
					// we fail here outright as this is not a documentation-completeness problem
					if (!option1.defaultValue.equals(option2.defaultValue)) {
						throw new AssertionError("Documentation contains distinct defaults for " +
							option1.key + " in " + option1.containingFile + " and " + option2.containingFile + '.');
					} else {
						throw new AssertionError("Documentation contains distinct descriptions for " +
							option1.key + " in " + option1.containingFile + " and " + option2.containingFile + '.');
					}
				}
			}));
	}

	private static Collection<DocumentedOption> parseDocumentedOptionsFromFile(Path file) throws IOException {
		Document document = Jsoup.parse(file.toFile(), StandardCharsets.UTF_8.name());
		return document.getElementsByTag("table").stream()
			.map(element -> element.getElementsByTag("tbody").get(0))
			.flatMap(element -> element.getElementsByTag("tr").stream())
			.map(tableRow -> {
				String key = tableRow.child(0).text();
				String defaultValue = tableRow.child(1).text();
				String description = tableRow.child(2).text();
				return new DocumentedOption(key, defaultValue, description, file.getName(file.getNameCount() - 1));
			})
			.collect(Collectors.toList());
	}

	private static Map<String, ExistingOption> findExistingOptions() throws IOException, ClassNotFoundException {
		Map<String, ExistingOption> existingOptions = new HashMap<>(32);

		for (OptionsClassLocation location : LOCATIONS) {
			processConfigOptions(System.getProperty("rootDir"), location.getModule(), location.getPackage(), optionsClass -> {
				List<ConfigOptionsDocGenerator.OptionWithMetaInfo> configOptions = extractConfigOptions(optionsClass);
				for (ConfigOptionsDocGenerator.OptionWithMetaInfo option : configOptions) {
					String key = option.option.key();
					String defaultValue = stringifyDefault(option);
					String description = option.option.description();
					ExistingOption duplicate = existingOptions.put(key, new ExistingOption(key, defaultValue, description, optionsClass));
					if (duplicate != null) {
						// multiple documented options have the same key
						// we fail here outright as this is not a documentation-completeness problem
						if (!(duplicate.description.equals(description))) {
							throw new AssertionError("Ambiguous option " + key + " due to distinct descriptions.");
						} else if (!duplicate.defaultValue.equals(defaultValue)) {
							throw new AssertionError("Ambiguous option " + key + " due to distinct default values (" + defaultValue + " vs " + duplicate.defaultValue + ").");
						}
					}
				}
			});
		}

		return existingOptions;
	}

	private static final class ExistingOption extends Option {

		private final Class<?> containingClass;

		private ExistingOption(String key, String defaultValue, String description, Class<?> containingClass) {
			super(key, defaultValue, description);
			this.containingClass = containingClass;
		}
	}

	private static final class DocumentedOption extends Option {

		private final Path containingFile;

		private DocumentedOption(String key, String defaultValue, String description, Path containingFile) {
			super(key, defaultValue, description);
			this.containingFile = containingFile;
		}
	}

	private abstract static class Option {
		protected final String key;
		protected final String defaultValue;
		protected final String description;

		private Option(String key, String defaultValue, String description) {
			this.key = key;
			this.defaultValue = defaultValue;
			this.description = description;
		}

		@Override
		public int hashCode() {
			return key.hashCode() + defaultValue.hashCode() + description.hashCode();
		}

		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof Option)) {
				return false;
			}

			Option other = (Option) obj;

			return this.key.equals(other.key)
				&& this.defaultValue.equals(other.defaultValue)
				&& this.description.equals(other.description);
		}

		@Override
		public String toString() {
			return "Option(key=" + key + ", default=" + defaultValue + ", description=" + description + ')';
		}
	}
}
