package org.icij.extract.core;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.io.Reader;
import java.io.IOException;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import org.apache.tika.metadata.Metadata;
import org.icij.task.Options;

/**
 * Base class for Spewer superclasses that write text output from a {@link ParsingReader} to specific endpoints.
 *
 * @since 1.0.0-beta
 */
public abstract class Spewer implements AutoCloseable {

	private Path outputBase = null;

	protected boolean outputMetadata = true;
	protected Charset outputEncoding = StandardCharsets.UTF_8;
	protected Map<String, String> tags = null;

	public Spewer() {

	}

	public Spewer(final Options<String> options) {
		options.get("output-metadata").parse().asBoolean().ifPresent(this::outputMetadata);
		options.get("output-encoding").value().ifPresent(this::setOutputEncoding);
		setTags(options.get("tag").values());
	}

	public abstract void write(final Path file, final Metadata metadata, final Reader reader) throws IOException;

	public void setOutputEncoding(final Charset outputEncoding) {
		this.outputEncoding = outputEncoding;
	}

	public void setOutputEncoding(final String outputEncoding) {
		setOutputEncoding(Charset.forName(outputEncoding));
	}

	public void setOutputBase(final Path outputBase) {
		this.outputBase = outputBase;
	}

	public void setOutputBase(final String outputBase) {
		setOutputBase(Paths.get(outputBase));
	}

	public Path getOutputBase() {
		return outputBase;
	}

	public void outputMetadata(final boolean outputMetadata) {
		this.outputMetadata = outputMetadata;
	}

	public boolean outputMetadata() {
		return outputMetadata;
	}

	public void setTags(final Map<String, String> tags) {
		this.tags = tags;
	}

	public void setTag(final String name, final String value) {
		if (null == tags) {
			tags = new HashMap<>();
		}

		tags.put(name, value);
	}

	private void setTags(final List<String> tags) {
		for (String tag : tags) {
			String[] pair = tag.split(":", 2);

			if (2 == pair.length) {
				setTag(pair[0], pair[1]);
			} else {
				throw new IllegalArgumentException(String.format("Invalid tag pair: \"%s\".", tag));
			}
		}
	}
}

@@ -702,16 +702,22 @@
 otected 
+final 
 Map%3CStri
@@ -732,27 +732,39 @@
 ng%3E tags = n
-ull
+ew HashMap%3C%3E();
 ;%0A%0A%09public S
@@ -772,19 +772,16 @@
 ewer() %7B
-%0A%0A%09
 %7D%0A%0A%09publ
@@ -1841,23 +1841,33 @@
 %0A%09%09t
-his.tags = tags
+ags.forEach(this::setTag)
 ;%0A%09%7D
@@ -1933,62 +1933,8 @@
 ) %7B%0A
-%09%09if (null == tags) %7B%0A%09%09%09tags = new HashMap%3C%3E();%0A%09%09%7D%0A%0A
 %09%09ta
@@ -2013,37 +2013,89 @@
 %7B%0A%09%09
-for (String tag :
+tags.forEach(this::setTag);%0A%09%7D%0A%0A%09private void setTag(final String
  tag
-s
 ) %7B%0A%09%09
-%09
+final 
 Stri
@@ -2128,17 +2128,16 @@
  2);%0A%0A%09%09
-%09
 if (2 ==
@@ -2152,17 +2152,16 @@
 ngth) %7B%0A
-%09
 %09%09%09setTa
@@ -2183,17 +2183,16 @@
 %5B1%5D);%0A%09%09
-%09
 %7D else %7B
@@ -2192,17 +2192,16 @@
  else %7B%0A
-%09
 %09%09%09throw
@@ -2284,13 +2284,8 @@
 ));%0A
-%09%09%09%7D%0A
 %09%09%7D%0A

Use Java 8 features