package org.approvaltests.core;

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

import org.approvaltests.Approvals;
import org.approvaltests.ReporterFactory;
import org.approvaltests.namer.ApprovalNamer;
import org.approvaltests.namer.NamerWrapper;
import org.approvaltests.scrubbers.NoOpScrubber;

import com.spun.util.ArrayUtils;

public class Options
{
  private final Map<String, Object> fields = new HashMap<>();
  public Options()
  {
  }
  public Options(Scrubber scrubber)
  {
    fields.put("scrubber", scrubber);
  }
  public Options(ApprovalFailureReporter reporter)
  {
    fields.put("reporter", reporter);
  }
  private Options(Map<String, Object> fields, String key, Object value)
  {
    this.fields.putAll(fields);
    this.fields.put(key, value);
  }
  public Options(Options parent, FileOptions fileOptions)
  {
    this(parent.fields, "fileOptions", fileOptions);
  }
  public ApprovalFailureReporter getReporter()
  {
    return ArrayUtils.getOrElse(fields, "reporter", ReporterFactory::get);
  }
  public Options withReporter(ApprovalFailureReporter reporter)
  {
    return new Options(fields, "reporter", reporter);
  }
  public Options withScrubber(Scrubber scrubber)
  {
    return new Options(fields, "scrubber", scrubber);
  }
  public String scrub(String input)
  {
    return getScrubber().scrub(input);
  }
  private Scrubber getScrubber()
  {
    return ArrayUtils.getOrElse(fields, "scrubber", () -> NoOpScrubber.INSTANCE);
  }
  public FileOptions forFile()
  {
    return new FileOptions(this.fields);
  }
  public static class FileOptions
  {
    private final Map<String, Object> fields;
    public FileOptions(Map<String, Object> fields)
    {
      this.fields = fields;
    }
    public Options withExtension(String fileExtensionWithDot)
    {
      if (!fileExtensionWithDot.startsWith("."))
      {
        fileExtensionWithDot = "." + fileExtensionWithDot;
      }
      return new Options(fields, "fileOptions.fileExtension", fileExtensionWithDot);
    }
    public ApprovalNamer getNamer()
    {
      return ArrayUtils.getOrElse(fields, "fileOptions.namer", Approvals::createApprovalNamer);
    }
    public String getFileExtension()
    {
      return ArrayUtils.getOrElse(fields, "fileOptions.fileExtension", () -> ".txt");
    }
    public Options withBaseName(String fileBaseName)
    {
      NamerWrapper approvalNamer = new NamerWrapper(() -> fileBaseName, getNamer());
      return new Options(fields, "fileOptions.namer", approvalNamer);
    }
    public Options withName(String fileBaseName, String extension)
    {
      NamerWrapper approvalNamer = new NamerWrapper(() -> fileBaseName, getNamer());
      HashMap<String, Object> newFields = new HashMap<>(fields);
      newFields.put("fileOptions.fileExtension", extension);
      return new Options(newFields, "fileOptions.namer", approvalNamer);
    }
  }
}

@@ -351,16 +351,135 @@
 tions%0A%7B%0A
+  private enum Fields %7B%0A                      SCRUBBER, REPORTER, FILE_OPTIONS_FILE_EXTENSION, FILE_OPTIONS_NAMER;%0A  %7D%0A
   privat
@@ -482,38 +482,38 @@
 ivate final Map%3C
-String
+Fields
 , Object%3E fields
@@ -614,26 +614,31 @@
 lds.put(
-%22scrubber%22
+Fields.SCRUBBER
 , scrubb
@@ -716,26 +716,31 @@
 lds.put(
-%22reporter%22
+Fields.REPORTER
 , report
@@ -762,38 +762,38 @@
 ate Options(Map%3C
-String
+Fields
 , Object%3E fields
@@ -794,22 +794,22 @@
 fields, 
-String
+Fields
  key, Ob
@@ -897,127 +897,8 @@
   %7D%0A
-  public Options(Options parent, FileOptions fileOptions)%0A  %7B%0A    this(parent.fields, %22fileOptions%22, fileOptions);%0A  %7D%0A
   pu
@@ -984,26 +984,31 @@
 fields, 
-%22reporter%22
+Fields.REPORTER
 , Report
@@ -1131,18 +1131,23 @@
 ds, 
-%22reporter%22
+Fields.REPORTER
 , re
@@ -1243,26 +1243,31 @@
 fields, 
-%22scrubber%22
+Fields.SCRUBBER
 , scrubb
@@ -1439,18 +1439,23 @@
 ds, 
-%22scrubber%22
+Fields.SCRUBBER
 , ()
@@ -1622,30 +1622,30 @@
 e final Map%3C
-String
+Fields
 , Object%3E fi
@@ -1673,30 +1673,30 @@
 Options(Map%3C
-String
+Fields
 , Object%3E fi
@@ -1970,35 +1970,42 @@
 ds, 
-%22fileOptions.fileExtension%22
+Fields.FILE_OPTIONS_FILE_EXTENSION
 , fi
@@ -2115,35 +2115,41 @@
 fields, 
-%22fileOptions.namer%22
+Fields.FILE_OPTIONS_NAMER
 , Approv
@@ -2270,35 +2270,42 @@
 ds, 
-%22fileOptions.fileExtension%22
+Fields.FILE_OPTIONS_FILE_EXTENSION
 , ()
@@ -2500,35 +2500,41 @@
 fields, 
-%22fileOptions.namer%22
+Fields.FILE_OPTIONS_NAMER
 , approv
@@ -2721,22 +2721,22 @@
 HashMap%3C
-String
+Fields
 , Object
@@ -2796,35 +2796,42 @@
 put(
-%22fileOptions.fileExtension%22
+Fields.FILE_OPTIONS_FILE_EXTENSION
 , ex
@@ -2880,27 +2880,33 @@
 ds, 
-%22fileOptions.namer%22
+Fields.FILE_OPTIONS_NAMER
 , ap

R convert to enum