package com.google.devtools.moe.client.project;

import com.google.devtools.moe.client.Injector;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Configuration for a scrubber.
 */
public class ScrubberConfig {

  // General options
  @SerializedName("ignore_files_re")
  private String ignoreFilesRe;

  @SerializedName("do_not_scrub_files_re")
  private String doNotScrubFilesRe;

  @SerializedName("extension_map")
  private JsonArray extensionMap;

  @SerializedName("sensitive_string_file")
  private String sensitiveStringFile;

  @SerializedName("sensitive_words")
  private List<String> sensitiveWords;

  @SerializedName("sensitive_res")
  private List<String> sensitiveRes;

  private List<JsonObject> whitelist;

  @SerializedName("scrub_sensitive_comments")
  private boolean scrubSensitiveComments = true;

  @SerializedName("rearranging_config")
  private JsonObject rearrangingConfig;

  @SerializedName("string_replacements")
  private List<Map<String, String>> stringReplacements;

  @SerializedName("regex_replacements")
  private List<Map<String, String>> regexReplacements;

  @SerializedName("scrub_non_documentation_comments")
  private boolean scrubNonDocumentationComments;

  @SerializedName("scrub_all_comments")
  private boolean scrubAllComments;

  // User options
  @SerializedName("usernames_to_scrub")
  private final List<String> usernamesToScrub = new ArrayList<>();

  @SerializedName("usernames_to_publish")
  private final List<String> usernamesToPublish = new ArrayList<>();

  @SerializedName("usernames_file")
  private String usernamesFile;

  @SerializedName("scrub_unknown_users")
  private boolean scrubUnknownUsers;

  @SerializedName("scrub_authors")
  private boolean scrubAuthors = true;

  // C/C++ options
  @SerializedName("c_includes_config_file")
  private String cIncludesConfigFile;

  @SerializedName("c_includes_config")
  private JsonObject cIncludesConfig;

  // Java options
  @SerializedName("empty_java_file_action")
  private String emptyJavaFileAction;

  @SerializedName("maximum_blank_lines")
  private int maximumBlankLines;
  @SerializedName("scrub_java_testsize_annotations")
  private boolean scrubJavaTestsizeAnnotations;

  @SerializedName("java_renames")
  private List<Map<String, String>> javaRenames;

  // JavaScript options
  @SerializedName("js_directory_rename")
  private Map<String, String> jsDirectoryRename;

  @SerializedName("js_directory_renames")
  private List<Map<String, String>> jsDirectoryRenames;

  // Python options
  @SerializedName("python_module_renames")
  private List<JsonObject> pythonModuleRenames;

  @SerializedName("python_module_removes")
  private List<JsonObject> pythonModuleRemoves;

  @SerializedName("python_shebang_replace")
  private JsonObject pythonShebangReplace;

  // GWT options
  @SerializedName("scrub_gwt_inherits")
  private List<String> scrubGwtInherits;

  // proto options
  @SerializedName("scrub_proto_comments")
  private boolean scrubProtoComments;

  private ScrubberConfig() { // Instantiated by GSON.
  }

  /**
   * @param author Author in the format "Name <username@domain>".
   */
  public boolean shouldScrubAuthor(String author) throws InvalidProject {
    if (!scrubAuthors) {
      return false;
    }
    // TODO(cgruber): Create a custom deserializer that does this logic once, on deserialization.
    if (usernamesFile != null) {
      try {
        UsernamesConfig usernamesConfig =
            ProjectConfig.makeGson()
                .fromJson(
                    Injector.INSTANCE.fileSystem().fileToString(new File(usernamesFile)),
                    UsernamesConfig.class);
        addUsernames(usernamesToScrub, usernamesConfig.getScrubbableUsernames());
        addUsernames(usernamesToPublish, usernamesConfig.getPublishableUsernames());
      } catch (IOException exception) {
        throw new InvalidProject(
            "File " + usernamesFile + " referenced by usernames_file not found.");
      }
      usernamesFile = null;
    }
    return scrubUnknownUsers
        ? !matchesUsername(author, usernamesToPublish)
        : matchesUsername(author, usernamesToScrub);
  }

  private void addUsernames(List<String> local, List<String> global) {
    if (global != null) {
      for (String username : global) {
        if (!local.contains(username)) {
          local.add(username);
        }
      }
    }
  }

  // TODO(cgruber): Parse out the actual usernames in a custom deserializer.
  private boolean matchesUsername(String author, List<String> usernames) {
    if (usernames != null) {
      for (String username : usernames) {
        if (author.matches(".*<" + Pattern.quote(username) + "@.*")) {
          return true;
        }
      }
    }
    return false;
  }
}

@@ -1562,38 +1562,32 @@
 rub%22)%0A  private 
-final 
 List%3CString%3E use
@@ -1678,14 +1678,8 @@
 ate 
-final 
 List

Remove "final" from serializable fields for GSON, which would otherwise silently ignore them. Change on 2015/07/10 by cgruber <cgruber@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=97997571