/*
 * Copyright 2021-2024 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.opentest4j.reporting.events.api;

import org.apiguardian.api.API;
import org.opentest4j.reporting.schema.QualifiedName;

import java.io.Closeable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

/**
 * Writer for documents with a certain root element type.
 *
 * @param <T> root element type
 * @since 0.1.0
 */
@API(status = EXPERIMENTAL, since = "0.1.0")
public interface DocumentWriter<T extends Element<T>> extends Closeable, Appendable<T> {

	/**
	 * Create a no-op implementation of {@code DocumentWriter}.
	 *
	 * @param <T> root element type
	 * @return no-op DocumentWriter
	 */
	static <T extends Element<T>> DocumentWriter<T> noop() {
		return new DocumentWriter<T>() {

			@Override
			public <C extends ChildElement<T, ? super C>> Appendable<T> append(Factory<C> creator,
					Consumer<? super C> configurer) {
				return this;
			}

			@Override
			public void close() {
			}
		};
	}

	/**
	 * Create a new document writer with the supplied root {@linkplain QualifiedName element name} and
	 * {@linkplain NamespaceRegistry namespace registry} that will write to the supplied {@linkplain Path XML file}.
	 *
	 * @param rootElementName   root element name
	 * @param namespaceRegistry namespace registry
	 * @param xmlFile           target XML file
	 * @param <R>               root element type
	 * @return new document writer
	 * @throws Exception in case there's an error opening the XML file or preparing the XML writing infrastructure
	 */
	static <R extends Element<R>> DocumentWriter<R> create(QualifiedName rootElementName,
			NamespaceRegistry namespaceRegistry, Path xmlFile) throws Exception {
		return new DefaultDocumentWriter<>(rootElementName, namespaceRegistry, Files.newBufferedWriter(xmlFile));
	}

}
