package com.urbancode.air.plugin.automation

import com.urbancode.air.http.*

public class QCAddComments extends AutomationBase {
    
    String bugPattern
    String failMode
    String additionalComments
    
    private def reqNumBugs
    private def idToChangeComment
    private def foundBugIds
    private def exitCode = 0
    
    public void execute() {
        init()
        
        idToChangeComment = getChangeSets()
        
        if (idToChangeComment && idToChangeComment.size()) {
            println "Defect Ids to comment on: " + idToChangeComment.keySet().join(", ")
            findBugs()
            addComment()
        }
        else {
            println "No defects found in source changes. Nothing to do."
        }
        
        if (exitCode != 0) {
            System.exit(1)
        }
    }
    
    private def getChangeSets() {
        def changesXml = HttpHelper.getChangeSets()
        
        def pattern = java.util.regex.Pattern.compile(bugPattern)
        def Map<String, String> idToChangeComment = new HashMap<String,String>()

        // will throw a parse exception at random times - any ideas?
        new XmlSlurper().parseText(changesXml)."change-set".each { element ->
            def matcher = pattern.matcher(element.comment.text())
            while (matcher.find()) {
                def patternid
                def comment
                if (matcher.groupCount() > 0) {
                    // they specified a '(...)' group within the pattern, use that as the bug-id
                    patternid = matcher.group(1)
                }
                else {
                    // use the whole matching substring as the bug-id
                    patternid = matcher.group()
                }
                comment = (element."comment".text())
                if (patternid != null && comment != null) {
                    idToChangeComment.put(patternid, comment)
                }
            }
        }
        
        return idToChangeComment
    }
    
    private void findBugs() {
        reqNumBugs = idToChangeComment.size()
        def bugIds = idToChangeComment.keySet().join(",")
        
        def outputFileName = ".numberOfBugsFound.txt"
        def findBugsCommand = [cscriptExe]
        findBugsCommand << PLUGIN_HOME + "\\qc_find_bugs.vbs"
        findBugsCommand << serverUrl
        findBugsCommand << username
        findBugsCommand << password
        findBugsCommand << domain
        findBugsCommand << project
        findBugsCommand << bugIds
        findBugsCommand << outputFileName

        cmdHelper.runCommand("Finding bugs to add comments to", findBugsCommand)
        
        verifyBugsFound(outputFileName)
    }
    
    private void verifyBugsFound(String outputFileName) {
        def outputFile = new File(outputFileName)
        foundBugIds = outputFile.text.split(",")
        def actNumBugs = foundBugIds.length
        outputFile.delete()
        
        println "Found $actNumBugs of $reqNumBugs defects in Quality Center."
        
        if (reqNumBugs != actNumBugs) {
            if (failMode == "slow") {
                println "Fail mode is 'Fail' and not all requested defects were found in Quality Center. Scheduling failure after the found defects have been updated."
                exitCode = 1
            }
            else if (failMode == "warn") {
                println "Fail mode is 'Warn' and not all requested defects were found in Quality Center. Only logging a warning."
            }
            else { // default is fast
                println "Fail mode is 'Fail-fast' and not all requested defects were found in Quality Center. Failing now."
                throw new Exception("Not all requested defects were found in Quality Center and fail mode is 'Fail-fast'")
            }
        }
    }
    
    private void addComment() {
        for (foundBugId in foundBugIds) {
            def comment = idToChangeComment.get(foundBugId) + " " + additionalComments
            def commentFile = new File(".qccomment.html")
            commentFile.text = createHtmlFormattedComment(username, comment)
            
            try {
                def addCommentCommand = [cscriptExe]
                addCommentCommand << PLUGIN_HOME + "\\qc_add_comment.vbs"
                addCommentCommand << serverUrl
                addCommentCommand << username
                addCommentCommand << password
                addCommentCommand << domain
                addCommentCommand << project
                addCommentCommand << foundBugId
                addCommentCommand << commentFile
                
                runCommand("Adding comment on defect $foundBugId", addCommentCommand)
            }
            finally {
                commentFile.delete()
            }
        }
    }
}