'''
Created on 2010/09/12

@author: tacky21jp
'''
class StepCounterBuilder:

    counter_map = {}

    def getCounter(self,fileName):

        if(fileName.endswith(".java")):
            counter = None
            if self.counter_map.has_key("Java"):
                counter = self.counter_map["Java"]
            else:
                counter = self.createJavaCounter("Java")
                self.counter_map["Java"] = counter
            return counter

        elif (fileName.endswith(".jsp")):
            counter = None
            if self.counter_map.has_key("JSP"):
                counter = self.counter_map["JSP"]
            else:
                counter = DefaultStepCounter();
                counter.addSingleLineComment("//")
                counter.addMultiLineComment("/*","*/")
                counter.addMultiLineComment("<%--","--%>")
                counter.addMultiLineComment("<!--","-->")
                counter.setFileType("JSP")
                self.counter_map["JSP"] = counter
            return counter

        elif (fileName.endswith(".js")):
            counter = None
            if self.counter_map.has_key("js"):
                counter = self.counter_map["js"]
            else:
                counter = self.createJavaCounter("js")
                self.counter_map["js"] = counter
            return counter

        elif (fileName.endswith(".cpp") or fileName.endswith(".c")):
            counter = None
            if self.counter_map.has_key("C/C++"):
                counter = self.counter_map["C/C++"]
            else:
                counter = self.createJavaCounter("C/C++")
                self.counter_map["C/C++"] = counter
            return counter

        elif (fileName.endswith(".h")):
            counter = None
            if self.counter_map.has_key("h"):
                counter = self.counter_map["h"]
            else:
                counter = self.createJavaCounter("h")
                self.counter_map["h"] = counter
            return counter

        elif (fileName.endswith(".cs")):
            counter = None
            if self.counter_map.has_key("C#"):
                counter = self.counter_map["C#"]
            else:
                counter = self.createJavaCounter("C#")
                self.counter_map["C#"] = counter
            return counter

        elif (fileName.endswith(".php") or fileName.endswith(".php3")):
            counter = None
            if self.counter_map.has_key("PHP"):
                counter = self.counter_map["PHP"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("//")
                counter.addMultiLineComment("/*","*/")
                counter.addMultiLineComment("<!--","-->")
                counter.setFileType("PHP")
                self.counter_map["PHP"] = counter
            return counter

        elif (fileName.endswith(".asp") or fileName.endswith(".asa") or fileName.endswith(".aspx") or fileName.endswith(".asax") or fileName.endswith(".ascx")):
            counter = None
            if self.counter_map.has_key("ASP"):
                counter = self.counter_map["ASP"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("'")
                counter.addSingleLineComment("//")
                counter.addMultiLineComment("/*","*/")
                counter.addMultiLineComment("<%--","--%>")
                counter.addMultiLineComment("<!--","-->")
                counter.setFileType("ASP")
                self.counter_map["ASP"] = counter
            return counter

        elif (fileName.endswith(".html") or fileName.endswith(".htm")):
            counter = None
            if self.counter_map.has_key("HTML"):
                counter = self.counter_map["HTML"]
            else:
                counter = self.createXMLCounter("HTML")
                self.counter_map["HTML"] = counter
            return counter

        elif (fileName.endswith(".vbs")):
            counter = None
            if self.counter_map.has_key("vbs"):
                counter = self.counter_map["vbs"]
            else:
                counter = self.createVBCounter("vbs")
                self.counter_map["vbs"] = counter
            return counter

        elif (fileName.endswith(".bas") or fileName.endswith(".frm") or fileName.endswith(".cls")):
            counter = None
            if self.counter_map.has_key("VB"):
                counter = self.counter_map["VB"]
            else:
                counter = self.createVBCounter("VB")
                self.counter_map["VB"] = counter
            return counter

        elif (fileName.endswith(".vb")):
            counter = None
            if self.counter_map.has_key("VB.NET"):
                counter = self.counter_map["VB.NET"]
            else:
                counter = self.createVBCounter("VB.NET")
                self.counter_map["VB.NET"] = counter
            return counter

        elif (fileName.endswith(".pl") or fileName.endswith(".pm")):
            counter = None
            if self.counter_map.has_key("Perl"):
                counter = self.counter_map["Perl"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("#")
                counter.addMultiLineComment("=pod","=cut")
                counter.setFileType("Perl")
                self.counter_map["Perl"] = counter
            return counter

        elif (fileName.endswith(".py")):
            counter = None
            if self.counter_map.has_key("Python"):
                counter = self.counter_map["Python"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("#")
                counter.setFileType("Python")
                self.counter_map["Python"] = counter
            return counter

        elif (fileName.endswith(".rb")):
            counter = None
            if self.counter_map.has_key("Ruby"):
                counter = self.counter_map["Ruby"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("#")
                counter.addMultiLineComment("=begin","=end")
                counter.setFileType("Ruby")
                self.counter_map["Ruby"] = counter
            return counter

        elif (fileName.endswith(".tcl")):
            return self.createShellCounter("Tcl");

        elif (fileName.endswith(".sql")):
            counter = None
            if self.counter_map.has_key("SQL"):
                counter = self.counter_map["SQL"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("#")
                counter.addSingleLineComment("--")
                counter.addSingleLineComment("REM")
                counter.addMultiLineComment("/*","*/");
                counter.setFileType("SQL")
                self.counter_map["SQL"] = counter
            return counter

        elif (fileName.endswith(".cfm")):
            counter = None
            if self.counter_map.has_key("CFM"):
                counter = self.counter_map["CFM"]
            else:
                counter = DefaultStepCounter()
                counter.addMultiLineComment("<!--","-->")
                counter.addMultiLineComment("<!---","--->")
                counter.setFileType("CFM")
                self.counter_map["CFM"] = counter
            return counter

        elif (fileName.endswith(".properties")):
            counter = None
            if self.counter_map.has_key("Properties"):
                counter = self.counter_map["Properties"]
            else:
                counter = self.createShellCounter("Properties")
                self.counter_map["Properties"] = counter
            return counter

        elif (fileName.endswith(".xml")):
            counter = None
            if self.counter_map.has_key("XML"):
                counter = self.counter_map["XML"]
            else:
                counter = self.createXMLCounter("XML")
                self.counter_map["XML"] = counter
            return counter

        elif (fileName.endswith(".xsl") or fileName.endswith(".xslt")):
            counter = None
            if self.counter_map.has_key("XSLT"):
                counter = self.counter_map["XSLT"]
            else:
                counter = self.createXMLCounter("XSLT")
                self.counter_map["XSLT"] = counter
            return counter

        elif (fileName.endswith(".dtd")):
            counter = None
            if self.counter_map.has_key("DTD"):
                counter = self.counter_map["DTD"]
            else:
                counter = self.createXMLCounter("DTD")
                self.counter_map["DTD"] = counter
            return counter

        elif (fileName.endswith(".tld")):
            counter = None
            if self.counter_map.has_key("TLD"):
                counter = self.counter_map["TLD"]
            else:
                counter = self.createXMLCounter("TLD")
                self.counter_map["TLD"] = counter
            return counter

        elif (fileName.endswith(".xsd")):
            counter = None
            if self.counter_map.has_key("XMLSchema"):
                counter = self.counter_map["XMLSchema"]
            else:
                counter = self.createXMLCounter("XMLSchema")
                self.counter_map["XMLSchema"] = counter
            return counter

        elif (fileName.endswith(".bat")):
            counter = None
            if self.counter_map.has_key("BAT"):
                counter = self.counter_map["BAT"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment("REM")
                counter.setFileType("BAT")
                self.counter_map["BAT"] = counter
            return counter

        elif (fileName.endswith(".css")):
            counter = None
            if self.counter_map.has_key("CSS"):
                counter = self.counter_map["CSS"]
            else:
                counter = DefaultStepCounter()
                counter.addMultiLineComment("/*","*/")
                counter.setFileType("CSS")
                self.counter_map["CSS"] = counter
            return counter

        elif (fileName.endswith(".l") or fileName.endswith(".el") or fileName.endswith(".cl")):
            counter = None
            if self.counter_map.has_key("Lisp"):
                counter = self.counter_map["Lisp"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment(";")
                counter.setFileType("Lisp")
                self.counter_map["Lisp"] = counter
            return counter

        elif (fileName.endswith(".ini")):
            counter = None
            if self.counter_map.has_key("INI"):
                counter = self.counter_map["INI"]
            else:
                counter = DefaultStepCounter()
                counter.addSingleLineComment(";")
                counter.setFileType("INI")
                self.counter_map["INI"] = counter
            return counter

        else:
            return None

    def createJavaCounter(self,name):
        counter = DefaultStepCounter()
        counter.addSingleLineComment("//")
        counter.addMultiLineComment("/*","*/")
        counter.setFileType(name)
        return counter

    def createVBCounter(self,name):
        counter = DefaultStepCounter()
        counter.addSingleLineComment("'")
        counter.addSingleLineComment("REM")
        counter.setFileType(name)
        return counter

    def createShellCounter(self,name):
        counter = DefaultStepCounter()
        counter.addSingleLineComment("#")
        counter.setFileType(name)
        return counter

    def createXMLCounter(self,name):
        counter = DefaultStepCounter()
        counter.addMultiLineComment("<!--","-->")
        counter.setFileType(name)
        return counter

class DefaultStepCounter:

    singleLineComment = []
    multiLineComment = []
    fileType = "UNDEF"

    def setFileType(self, fileType):
        self.fileType = fileType

    def getFileType(self):
        return self.fileType

    def addSingleLineComment(self, str):
        self.singleLineComment.append(str)

    def getSingleLineComment(self):
        return self.singleLineComment

    def addMultiLineComment(self, comment_from,comment_to):
        self.multiLineComment.append([comment_from,comment_to])

    def getMultiLineComment(self):
        return self.multiLineComment

    def countContent(self,content):
        step    = 0
        non     = 0
        comment = 0
        multiLineFlag = False
        lastLineComment = []
        for line in content.split("\n"):
            if(multiLineFlag==False):
                if(self.nonCheck(line.strip())):
                    non = non + 1
                elif(self.isSingleLineComment(line.strip())):
                    comment = comment + 1
                else:
                    lastLineComment = self.isMultiLineCommentStart(line,comment)
                    if(lastLineComment!=None):
                        comment = comment + 1
                        multiLineFlag = True
                    else:
                        step = step + 1
            else:
                comment = comment + 1
                if (self.isMultiLineCommentEnd(line,lastLineComment)):
                    multiLineFlag = False

        return StepCountResult('',self.getFileType(),step,non,comment)

    def nonCheck(self,line):
        if(line==''):
            return True
        else:
            return False

    def isSingleLineComment(self, line):
        dim = self.getSingleLineComment()
        for d in dim:
            if(line.startswith(d)):
                return True

        area = self.getMultiLineComment()
        for a in area:
            start = a[0]
            end   = a[1]

            idx = line.find(start);
            if(idx==0 and line.find(end,idx)==len(line)-len(end)):
                return True

        return False

    def isMultiLineCommentStart(self,line,comment):
        area = self.getMultiLineComment()
        for a in area:
            start = a[0]
            end   = a[1]

            idx = line.find(start)
            if(idx>=0 and line.find(end,idx)<0):
                return a
        return None

    def isMultiLineCommentEnd(self,line,area):
        end = area[1]
        if(line.find(end)>=0):
            return True
        else:
            return False

class StepCountResult:

    def __init__(self,fileName,fileType,step,nonStep,comment):
        self.fileName = fileName
        self.fileType = fileType
        self.step = step
        self.nonStep = nonStep
        self.commentStep = comment

    def getFileName(self):
        return self.fileName

    def getFileType(self):
        return self.fileType

    def getStep(self):
        return self.step

    def getNonStep(self):
        return self.nonStep

    def getCommentStep(self):
        return self.commentStep

    def toString(self):
        return "%s,%s,%d,%d,%d" % self.getFileName(),self.getFileType(),self.getStep(),self.getNonStep,self.getCommentStep()

