package com.urbancode.air.plugin.analytics;

import org.xml.sax.SAXException;

public class SonargraphHandler extends org.xml.sax.helpers.DefaultHandler {

    def tagNameStack = new Stack()
    def findingId = ""
    def findingFile = ""
    def findingLine = ""
    def findingName = ""
    def findingSeverity = ""
    def findingDesc
    def addFinding
    boolean inWarning = false
    boolean inViolation = false
    boolean foundPosition = false
    String baseWarningDescription = ""

    SonargraphHandler(def addFinding) {
        this.addFinding = addFinding
    }

    void startElement(String ns, String localName, String qName, org.xml.sax.Attributes attribs) {
        switch (qName) {
            case 'warningsByAttribute':
                baseWarningDescription = attribs.getValue("attributeDescription")
                findingName = attribs.getValue("attributeName")
                try {
                    String warningInfo = attribs.getValue("warningInfo")
                    if (warningInfo) {
                        findingName += ": ${warningInfo}"
                    }
                }
                catch (Exception e) {
                    // Swallow
                }
                break
            
            case 'warnings':
                findingSeverity = "warning"
                inWarning = true
                break
            
            case 'warning':
                findingDesc = new StringBuilder(baseWarningDescription)
                break
            
            case 'violations':
                findingSeverity = "violation"
                findingDesc = new StringBuilder()
                break
            
            case 'architectureViolations':
                inViolation = true
                findingName = attribs.getValue("explanation")
                break
            
            case 'typeRelation':
            findingDesc = new StringBuilder(baseWarningDescription)
            break
            
            case 'attribute':
                String attribName = attribs.getValue("name")
                String value = attribs.getValue("value")
                if (inWarning) {
                    if (attribName == "Attribute value" && value) {
                        findingDesc.append(": ${value}")
                    }
                    else if (attribName == "Element" && value) {
                        int index = value.indexOf("::");
                        if (index > 0) {
                            value = value.substring(0, index)
                        }
                        findingFile = value
                    }
                }
                else if (inViolation) {
                    if (attribName == "Explanation" && value) {
                        findingDesc.append("${value}")
                    }
                    else if (attribName == "From" && value) {
                        findingFile = value
                    }
                }
                break
            
            case 'position':
                findingLine = attribs.getValue("line")
                findingFile = attribs.getValue("file")
                break
        }
        tagNameStack.push(qName)
    }
    
    void endElement(String ns, String localName, String qName) {
        tagNameStack.pop()
        switch (qName) {
            case 'warnings':
                inWarning = false
                break
            
            case 'architectureViolations':
                inViolation = false
                break
                
            case 'typeRelation':
            case 'warning':
                if (!foundPosition) {
                    addFinding('', findingFile, findingLine, findingName, findingSeverity, findingDesc.toString(), '')
                }
                else {
                    foundPosition = false
                }
                break
            
            case 'position':
                foundPosition = true
                addFinding('', findingFile, findingLine, findingName, findingSeverity, findingDesc.toString(), '')
                findingLine = ""
                findingFile = ""
                break
        }
    }
}
