import groovy.io.FileType
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType

ext {
    autoResConfig = this.&autoResConfig
}

def allStringsResourceFiles(@ClosureParams(value = SimpleType.class, options = ['java.io.File']) Closure c) {
    file('src/main/res').eachFileRecurse(FileType.FILES) { f ->
        if (f.name == 'strings.xml') {
            c(f)
        }
    }
}

/**
 * Discovers supported languages listed as under the res/values- directory.
 */
def autoResConfig() {
    def files = []
    allStringsResourceFiles { f ->
        files.add(f.parentFile.name)
    }
    ['en'] + files.collect { f -> f =~ /^values-([a-z]{2}(-r[A-Z]{2})?)$/ }
            .findAll { matcher -> matcher.find() }
            .collect { matcher -> matcher.group(1) }
            .sort()
}

task pullTranslations(type: Exec) {
    group 'Translate'
    description 'Pull translations, requires transifex client and api key.'
    commandLine 'tx', 'pull', '-a', '--minimum-perc=80', '--force'
}

task replaceEllipsis {
    group 'Translate'
    description 'Process strings for ellipsis characters.'
    doLast {
        allStringsResourceFiles { f ->
            def before = f.text
            def after = f.text.replace('...', '…')
            if (before != after) {
                f.text = after
                logger.info("$f.parentFile.name/$f.name...updated")
            }
        }
    }
    mustRunAfter pullTranslations
}

task cleanApostropheErrors {
    group 'Translate'
    description 'Fix transifex apostrophe string errors.'
    doLast {
        allStringsResourceFiles { f ->
            def before = f.text
            def after = before.replaceAll(/([^\\=08])(')/, '$1\\\\\'')
            if (before != after) {
                f.text = after
                logger.info("$f.parentFile.name/$f.name...updated")
            }
        }
    }
    mustRunAfter replaceEllipsis
}

task excludeNonTranslatables {
    group 'Translate'
    description 'Remove strings that are marked "translatable"="false" or are ExtraTranslations.'
    doLast {
        def englishFile = file('src/main/res/values/strings.xml')

        def english = new XmlParser().parse(englishFile)
        def nonTranslatable = english
                .findAll { it['@translatable'] == 'false' }
                .collect { it['@name'] }
                .toSet()
        def all = english.collect { it['@name'] }.toSet()
        def translatable = all - nonTranslatable
        def inMultiline = false
        def endBlockName = ""

        allStringsResourceFiles { f ->
            if (f != englishFile) {
                def newLines = f.readLines()
                        .collect { line ->
                            if (!inMultiline) {
                                def singleLineMatcher = line =~ /name="([^"]*)".*<\//
                                if (singleLineMatcher.find()) {
                                    def name = singleLineMatcher.group(1)
                                    if (!line.contains('excludeNonTranslatables') && !translatable.contains(name)) {
                                        return "  <!-- Removed by excludeNonTranslatables ${line.trim()} -->"
                                    }
                                } else {
                                    def multilineStartMatcher = line =~ /<(.*) .?name="([^"]*)".*/
                                    if (multilineStartMatcher.find()) {
                                        endBlockName = multilineStartMatcher.group(1)
                                        def name = multilineStartMatcher.group(2)
                                        if (!line.contains('excludeNonTranslatables') && !translatable.contains(name)) {
                                            inMultiline = true;
                                            return "  <!-- Removed by excludeNonTranslatables ${line.trim()}"
                                        }
                                    }
                                }
                            } else {
                                def multilineEndMatcher = line =~ /<\/${endBlockName}/
                                if (multilineEndMatcher.find()) {
                                    inMultiline = false
                                    return "${line} -->"
                                }
                            }

                            return line
                        }

                f.write(newLines.join("\n") + "\n")
            }
        }
    }
    mustRunAfter cleanApostropheErrors
}

task postTranslateQa {
    group 'Translate'
    description 'Runs QA to check validity of updated strings, and ensure presence of any new languages in internal lists.'
    dependsOn ':qa'
    mustRunAfter excludeNonTranslatables
}

task translate {
    group 'Translate'
    description 'Pull translations and post-process for ellipsis, apostrophes and non-translatables.'
    dependsOn pullTranslations, replaceEllipsis, cleanApostropheErrors, excludeNonTranslatables, postTranslateQa
}
