package org.mutabilitydetector.findbugs;

import static org.mutabilitydetector.MutabilityReason.CANNOT_ANALYSE;
import static org.mutabilitydetector.MutabilityReason.NOT_DECLARED_FINAL;
import static org.mutabilitydetector.MutabilityReason.NULL_REASON;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

import org.mutabilitydetector.MutabilityReason;

public class WriteFindBugsConfigFiles {

    
    public static void main(String[] args) throws Exception {
        writeMessagesXml();
        writeFindbugsXml();
    }

    private static void writeMessagesXml() throws Exception {
        StringBuilder content = new StringBuilder();
        
        content.append("<MessageCollection>\n\n")
        .append("<Plugin>\n")
        .append("<ShortDescription>MutabilityDetector4FindBugs plugin</ShortDescription>\n")
        .append("<Details>\n")
        .append("<![CDATA[\n")
        .append("<p>This plugin detects classes annotated with @Immutable that are actually mutable</p>\n")
        .append("]]>\n")
        .append("</Details>\n")
        .append("</Plugin>\n\n\n")
        
        .append("<Detector class=\"" + ThisPluginDetector.class.getName() + "\">\n")
        .append("<Details>\n")
        .append("<![CDATA[\n")
        .append("<p>This plugin detects classes annotated with @Immutable that are actually mutable</p>\n")
        .append("]]>\n")
        .append("</Details>\n")
        .append("</Detector>\n")
        
        .append("\n<!-- Each of the individual reasons for mutability -->\n");
        
        for (MutabilityReason reason : MutabilityReason.values()) {
            if (isReasonToExclude(reason)) { continue; }
            
            content.append("<BugPattern type=\"MUTDEC_" + reason.name() + "\">\n")
            .append("<ShortDescription>@Immutable class is actually mutable</ShortDescription>\n")
            .append("<LongDescription>\n")
            
            .append(reason.description() + "\n")
            
            .append("</LongDescription>\n");
            
            writeEmptyDetailsNode(content)
            .append("</BugPattern>\n")
            .append("\n");
        }
        
        content.append("</MessageCollection>\n");
        
        writeFile("src/main/resources/messages.xml", content);
    }

    private static void writeFindbugsXml() throws Exception {
        StringBuilder content = new StringBuilder();
        
        content.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
        .append("<FindbugsPlugin xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" defaultenabled=\"true\" >\n")
        .append("<Detector class=\"" + ThisPluginDetector.class.getName() + "\" speed=\"fast\" />\n\n")
        .append("<!-- Each bug pattern -->\n");
        
        for (MutabilityReason reason : MutabilityReason.values()) {
            if (isReasonToExclude(reason)) { continue; }
            
            content.append("<BugPattern type=\"MUTDEC_" + reason.name() + "\" abbrev=\"MUTDEC\" category=\"CORRECTNESS\">\n");
            
            writeEmptyDetailsNode(content);
            
            content.append("</BugPattern>\n");
            
        }

        content.append("</FindbugsPlugin>\n");
        
        writeFile("src/main/resources/findbugs.xml", content);
    }

    private static StringBuilder writeEmptyDetailsNode(StringBuilder content) {
        content.append("<Details>\n")
               .append("<![CDATA[]]>\n")
               .append("</Details>\n");
        
        return content;
    }
    
    @SuppressWarnings("deprecation")
    private static boolean isReasonToExclude(MutabilityReason reason) {
        return reason.isOneOf(NULL_REASON, CANNOT_ANALYSE, NOT_DECLARED_FINAL);
    }

    private static void writeFile(String fileName, StringBuilder content) throws IOException {
        System.out.println(content);
        new BufferedWriter(new FileWriter(fileName)).append(content).close();
    }
    
}

@@ -35,16 +35,55 @@
 dbugs;%0A%0A
+import static java.lang.String.format;%0A
 import s
@@ -1733,32 +1733,151 @@
  %7D%0A            %0A
+            String description = format(%22@Immutable class is actually mutable (%25s)%22, humanReadableReasonCode(reason));%0A
             cont
@@ -1986,44 +1986,27 @@
 ion%3E
-@Immutable class is actually mutable
+%22 + description + %22
 %3C/Sh
@@ -2067,108 +2067,24 @@
 ion%3E
-%5Cn%22)%0A            %0A            .append(reason.description() + %22%5Cn%22)%0A            %0A            .append(
+%22+ description +
 %22%3C/L
@@ -2126,37 +2126,32 @@
            write
-Empty
 DetailsNode(cont
@@ -2153,16 +2153,24 @@
 (content
+, reason
 )%0A      
@@ -2277,102 +2277,377 @@
 d(%22%3C
-/MessageCollection%3E%5Cn%22);%0A        %0A        writeFile(%22src/main/resources/messages.xml%22, content
+BugCode abbrev=%5C%22MUTDEC%5C%22%3EClass annotated with @Immutable is actually mutable%3C/BugCode%3E%5Cn%5Cn%22);%0A        %0A        content.append(%22%3C/MessageCollection%3E%5Cn%22);%0A        %0A        writeFile(%22src/main/resources/messages.xml%22, content);%0A    %7D%0A%0A    private static String humanReadableReasonCode(MutabilityReason reason) %7B%0A        return reason.code().replace(%22_%22, %22 %22).toLowerCase(
 );%0A 
@@ -3528,25 +3528,24 @@
  %0A        %7D%0A
-%0A
         cont
@@ -3891,24 +3891,336 @@
 ntent;%0A    %7D
+%0A%0A    private static StringBuilder writeDetailsNode(StringBuilder content, MutabilityReason reason) %7B%0A        content.append(%22%3CDetails%3E%5Cn%22)%0A        .append(%22%3C!%5BCDATA%5B%5Cn%22)%0A        .append(reason.description() + %22%5Cn%22)%0A        .append(%22%5D%5D%3E%5Cn%22)%0A        .append(%22%3C/Details%3E%5Cn%22);%0A        %0A        return content;%0A    %7D
 %0A    %0A    @S

Change long description to be a bit less verbose, move that description to details node, include bugCode element.