#!/usr/bin/python

import os, re, shutil, time, sys, md5

def main():
    makeCompDir(".")

    # generate md5sum file
    fmd5 = open(Md5SumFileTmp, "w")

    hashtree = {}
    jscount = 0
    csscount = 0
    othercount = 0
    for dirpath, dirnames, filenames in Tree:
        # exclude some dirs
        if ExcludeDirsRe.search(dirpath):
            continue

        # save file to md5sums list
        for name in filenames:
            path = getPath(dirpath, name)
            if JSFilesRe.search(name) or CSSFilesRe.search(name) or OtherFilesRe.search(name):
                fmd5.write(getMd5File(path) + " " + path + "\n")

        # find js-files in current dirpath
        jsfiles = getFiles(dirpath, filenames, JSFilesRe)

        # find js-files in current dirpath
        cssfiles = getFiles(dirpath, filenames, CSSFilesRe)

        # find other files
        otherfiles = getFiles(dirpath, filenames, OtherFilesRe)

        jslen = len(jsfiles)
        csslen = len(cssfiles)
        otherlen = len(otherfiles)

        # continue if no files
        if jslen + csslen + otherlen == 0:
            continue

        jscount += jslen
        csscount += csslen
        othercount += otherlen

        # create dir for files
        path = makeCompDir(dirpath)

        hashtree[path] = {'jsfiles': jsfiles, 'cssfiles': cssfiles}

        # copy other files to compdir
        for name in otherfiles:
            shutil.copy(name, path)

    fmd5.close()

    # compress js-files
    i = float(0)
    times = float(0)
    for path in hashtree:
        for name in hashtree[path]['jsfiles']:
            start = time.time()

            # operation
            i += 1

            if not(compressJS(name, os.path.join(CompDir, name))):
                shutil.copy(name, path)
            
            # /operation

            times += time.time() - start

            sys.stdout.write(getTTE(i, jscount + csscount, times, name))
            sys.stdout.flush()
    
        for name in hashtree[path]['cssfiles']:
            start = time.time()

            # operation
            i += 1

            if not(compressCSS(name, os.path.join(CompDir, name))):
                shutil.copy(name, path)
            
            # /operation

            times += time.time() - start

            sys.stdout.write(getTTE(i, jscount + csscount, times, name))
            sys.stdout.flush()
    
    shutil.move(Md5SumFileTmp, Md5SumFile)
    
    if i != 0:
        print("\ndone")

    

def getPath(dirpath, name):
    return os.path.normpath(os.path.join(dirpath, name))

# get files by regex
def getFiles(dirpath, filenames, regex):
    ret = []
    for name in filenames:
        path = getPath(dirpath, name)
        if regex.search(name) and not(checkMd5File(path)):
            ret.append(path)

    return ret

# make dir in compressed folder
def makeCompDir(name):
    path = getPath(CompDir, name)
    try:
        os.makedirs(path)
    except OSError:
        pass
    return path

def getTTE(i, count, times, name):
    # current file number
    curprogress = i / count
    endprogress = 1.0 - curprogress
    alltime = (times / i) * count
    tte = alltime * endprogress

#    return "\r" + chr(27) + "[0K%3d%%, %d of %d, tte: %ds, %s" % (100 * curprogress, i, count, tte, name)
    return "%3d%%, %d of %d, tte: %ds, %s\n" % (100 * curprogress, i, count, tte, name)

def execCommand(cmd):
    child = os.popen(cmd)
    data = child.read()
    err = child.close()
    if err:
        sys.stderr.write("%r failed with exit code %d\n" % (cmd, err))
        return False
    return True

def getMd5File(fname):
    f = open(fname)
    md5sum = md5.md5(f.read()).hexdigest()
    f.close()

    return md5sum

def getMd5Hash(fname):
    md5sums = []
    try:
        for line in open(fname):
            md5sums.append(line)
    except:
        pass

    return "".join(md5sums)

def checkMd5File(fname):
    reg = re.compile(getMd5File(fname) + " " + fname)
    return reg.search(Md5Sums)

def compressJS(fname, sname):
    proc = "java -jar yuicompressor.jar --type js --charset utf-8 -o"
    if (JSSafeFilesRe.search(fname)):
        proc = "jsmin >"
    return execCommand("cat '" + fname + "' | grep -v 'y5\.Console\.' | " + proc + " '" + sname + "'")

def compressCSS(fname, sname):
    return execCommand("cat '" + fname + "' | java -jar yuicompressor.jar --type css --charset utf-8 -o '" + sname + "'")

CurDir = os.getcwd()
CompDir = CurDir + "-c"
Md5SumFile = "md5sums"
Md5SumFileTmp = "md5sums.tmp"
Md5Sums = getMd5Hash(Md5SumFile)
JSFilesRe = re.compile(r'\.js$')
JSSafeFilesRe = re.compile(r'^XXX\.js$')
CSSFilesRe = re.compile(r'\.css$')
OtherFilesRe = re.compile(r'\.(html?|png|gif|jpeg)$')
ExcludeDirsRe = re.compile(r'\.svn|^\.\/tests|^\.\/docs|^\.\/FireBug')
Tree = os.walk(".")

main()
