#!/bin/bash
PIWIKPATH=$PWD/..
GitBranchName="translationupdates"
DOWNLOADPATH="${PIWIKPATH}/tmp/oTrance"
pluginName=""

################################
# Fetches package from oTrance
# Downloaded archive will be extraced and containing php files will be converted to json
#
function fetchTranslationsFromOTrance() {

    OTranceUser="downloaduser"

    # create oTrance directory in tmp folder
    mkdir ${DOWNLOADPATH} > /dev/null 2>&1

    read -s -p "Please provide the OTrance password for 'downloaduser'? " OTrancePassword

    # login to oTrance and save cookie as file to us for following requests
    echo "Starting to fetch latest language pack"
    wget --save-cookies ${DOWNLOADPATH}/cookies.txt \
         --quiet \
         -O - \
         --keep-session-cookies \
         --post-data "user=${OTranceUser}&pass=${OTrancePassword}&autologin=1" \
         http://translations.piwik.org/public/index/login \
         > /dev/null 2>&1

    # ask to create a new download package
    while true; do
        read -p "Shall we create a new language pack? " yn
        case ${yn} in
            [Yy]* ) wget --load-cookies ${DOWNLOADPATH}/cookies.txt \
                         --quiet \
                         -O - \
                         http://translations.piwik.org/public/export/update.all \
                         > /dev/null 2>&1; break;;
            [Nn]* ) echo "Searching for existing packs instead"; break;;
            * ) echo "Please answer yes or no. ";;
        esac
    done

    # Search for package and download it
    downloadfile=(`wget --load-cookies ${DOWNLOADPATH}/cookies.txt \
                        --quiet \
                        -O - \
                        http://translations.piwik.org/public/downloads/ \
                        | grep -Pom 1 '(language\_pack\-[0-9]{8}\-[0-9]{6}\.tar\.gz)'`)

    while true; do
        read -p "Found language pack $downloadfile. Proceed? " yn
        case ${yn} in
            [Yy]* ) break;;
            [Nn]* ) exit;;
            * ) echo "Please answer yes or no. ";;
        esac
    done

    wget --load-cookies ${DOWNLOADPATH}/cookies.txt \
         -O ${DOWNLOADPATH}/language_pack.tar.gz \
         http://translations.piwik.org/public/downloads/download/file/$downloadfile

    # remove cookie file
    rm -f ${DOWNLOADPATH}/cookies.txt

    # extract package
    echo "Extracting package..."
    cd ${DOWNLOADPATH}
    gunzip -q -c ${DOWNLOADPATH}/language_pack.tar.gz | tar xvf - > /dev/null 2>&1

    if [ $? -gt 0 ]; then
        echo "Error: Unable to extract download package. Aborting..."
        exit;
    fi

    # remove downloaded file
    rm -f ${DOWNLOADPATH}/language_pack.tar.gz

    rm -f ${DOWNLOADPATH}/en.php

    # convert downloaded php files to json
    cd ${DOWNLOADPATH}
    php -r '
    $nest = true;
    foreach (glob("*.php") as $filename) {
        echo sprintf("Converting %s\n", basename($filename));
        require_once basename($filename);
        $basename = explode(".", basename($filename));
        if ($nest) {
            $nested = array();
            foreach ($translations as $key => $value) {
                list($plugin, $nkey) = explode("_", $key, 2);
                $nested[$plugin][$nkey] = $value;
            }
            $translations = $nested;
        }
        $data = json_encode($translations, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        $newFile = sprintf("%s.json", $basename[0]);
        file_put_contents($newFile, $data);
    }'
    cd ${DOWNLOADPATH}

    rm -f *.php
}
#
################################

################################
# Creates a pull request ${GitBranchName} > piwik/master
#
function createPullRequest() {

        while true; do
        read -p "Please provide your github username (to create a pull request using Github API): " username

        returnCode=(`curl \
             -X POST \
             -k \
             --silent \
             --write-out %{http_code} \
             --stderr /dev/null \
             -o /dev/null \
             -u ${username} \
             --data "{\"title\":\"automatic translation update\",\"body\":\"autogenerated translation update\",\"head\":\"${GitBranchName}\",\"base\":\"master\"}" \
             -H 'Accept: application/json' \
             https://api.github.com/repos/piwik/piwik/pulls`);

        if [ ${returnCode} -eq 401 ]; then
            echo "Pull request failed. Bad credentials... Please try again"
            continue;
        fi

        if [ ${returnCode} -eq 422 ]; then
            echo "Pull request failed. Unprocessable Entity. Maybe a pull request was already created before."
            break;
        fi

        if [ ${returnCode} -eq 201 ]; then
            echo "Pull request successfully created."
            break;
        fi

        if [ ${returnCode} -eq 200 ]; then
            echo "Pull request successfully created."
            break;
        fi

        echo "Pull request failed."

    done
}
#
################################

################################
# Merge ${GitBranchName} with current master
#
function mergeBranchWithMaster() {

    cd ${PIWIKPATH};

    git checkout master > /dev/null 2>&1
    git pull > /dev/null 2>&1
    git submodule init > /dev/null 2>&1
    git submodule update > /dev/null 2>&1

    if [ ${pluginName} ]; then
        cd ${PIWIKPATH}/plugins/${pluginName}
        git checkout master > /dev/null 2>&1
        git pull > /dev/null 2>&1
    fi;

    # check if branch exists local (assume its the correct one if so)
    git branch | grep ${GitBranchName} > /dev/null 2>&1

    if [ $? -eq 1 ]; then
        git checkout -b ${GitBranchName} origin/${GitBranchName} > /dev/null 2>&1
    fi

    # switch to branch and merge with master
    git checkout ${GitBranchName} > /dev/null 2>&1
    git merge master > /dev/null 2>&1
    git push origin ${GitBranchName} > /dev/null 2>&1
}
#
################################

################################
# Commit new language files
#
function commitLanguageFiles() {

    cd ${PIWIKPATH}

    if [ ${pluginName} ]; then
        cd plugins/${pluginName}
    fi;

    git add lang/. > /dev/null 2>&1

    git commit -m "language update ${pluginName} refs #3430"
    git push
}
#
################################

################################
# prints all available language codes
#
function showAvailableLanguageCodes() {

    ls -1 ${PIWIKPATH}/lang | grep .json | awk '{print substr($1, 0, length($1)-5)}' | uniq | sort
}
#
################################

################################
# prints all available language names
#
function showAvailableLanguageName() {

    grep -rh 'EnglishLanguageName' ${PIWIKPATH}/lang | awk '{print substr($0, 33, length($0)-34)}' | uniq | sort
}
#
################################

################################
# prints all available plugins that have their own translation files
#
function showPluginsWithTranslations() {

    ls -d1 ${PIWIKPATH}/plugins/*/lang | egrep -o "([a-zA-Z]+)/lang" | awk '{print substr($1, 0, length($1)-5)}' | uniq | sort
}
#
################################

################################
# prints all translation keys that could be found within the piwik code
#
function showTranslationKeysInUse() {

    (
     (grep -rhose "'\([a-zA-Z0-9_-]\+\)'|translate" ${PIWIKPATH}/plugins/ | awk '{print substr($1,2,length($1)-12)}');
     (grep -rhose "'\([a-zA-Z0-9_-]\+\)'|translate" ${PIWIKPATH}/core/ | awk '{print substr($1,2,length($1)-12)}');
     (grep -rhose "Piwik_Translate(['\"][a-zA-Z0-9_-]\+['\"]" ${PIWIKPATH}/plugins/ | awk '{print substr($1,18,length($1)-18)}');
     (grep -rhose "Piwik_Translate(['\"][a-zA-Z0-9_-]\+['\"]" ${PIWIKPATH}/core/ | awk '{print substr($1,18,length($1)-18)}');
     (grep -rhose "pk_translate(['\"][a-zA-Z0-9_-]\+['\"]" ${PIWIKPATH}/plugins/ | awk '{print substr($1,15,length($1)-15)}');
     (grep -rhose "pk_translate(['\"][a-zA-Z0-9_-]\+['\"]" ${PIWIKPATH}/core/ | awk '{print substr($1,15,length($1)-15)}')
    ) | sort | uniq
}
#
################################

################################
#
function setTranslationsForLanguage() {

    languageCode=${1};
    translationFile=${2};

    if [ "$#" -lt 2 ]; then
        echo "language code and path to translation file required";
        return 1;
    fi

    # second parameter needs to be a already existing core language
    existingLanguages=(`showAvailableLanguageCodes`);
    if [[ ! ${existingLanguages[@]} =~ ${1} ]]; then
        echo "language '${1}' doesn't exist in PIWIK";
        return 1;
    fi

    # second parameter needs to be a readable file
    if [ ! -r ${2} ]; then
        echo "given translation file '${2}' is not readable or doesn't exist";
        return 1;
    fi

    echo "Starting to import data from '${2}' to language '${1}'";

    php -r '
        define("PIWIK_INCLUDE_PATH", "'${PIWIKPATH}'");
        define("PIWIK_INCLUDE_SEARCH_PATH", get_include_path()
            . PATH_SEPARATOR . "'${PIWIKPATH}'/core"
            . PATH_SEPARATOR . "'${PIWIKPATH}'/libs"
            . PATH_SEPARATOR . "'${PIWIKPATH}'/plugins");
        @ini_set("include_path", PIWIK_INCLUDE_SEARCH_PATH);
        @set_include_path(PIWIK_INCLUDE_SEARCH_PATH);

        require_once PIWIK_INCLUDE_PATH . "/libs/upgradephp/upgrade.php";
        require_once PIWIK_INCLUDE_PATH . "/core/Loader.php";
        require_once PIWIK_INCLUDE_PATH . "/vendor/autoload.php";

        use Piwik\Translate\Writer;
        use Piwik\Translate\Validate\NoScripts;
        use Piwik\Translate\Validate\CoreTranslations;
        use Piwik\Translate\Filter\ByBaseTranslations;
        use Piwik\Translate\Filter\ByParameterCount;
        use Piwik\Translate\Filter\EmptyTranslations;
        use Piwik\Translate\Filter\EncodedEntities;
        use Piwik\Translate\Filter\UnnecassaryWhitespaces;

        $plugin = "'${pluginName}'";
        $translationWriter = new Writer("'${1}'", $plugin);

        $baseTranslations = $translationWriter->getTranslations("en");

        $translationWriter->addValidator(new NoScripts());
        if (empty($plugin)) {
            $translationWriter->addValidator(new CoreTranslations($baseTranslations));
        }

        $translationWriter->addFilter(new ByBaseTranslations($baseTranslations));
        $translationWriter->addFilter(new EmptyTranslations());
        $translationWriter->addFilter(new ByParameterCount($baseTranslations));
        $translationWriter->addFilter(new UnnecassaryWhitespaces($baseTranslations));
        $translationWriter->addFilter(new EncodedEntities());

        $translationData = file_get_contents("'${2}'");
        $translations = json_decode($translationData, true);

        $translationWriter->setTranslations($translations);

        if (!$translationWriter->isValid()) {
            die("Failed setting translations:" . $translationWriter->getValidationMessage() . "\n");
        }

        if (!$translationWriter->hasTranslations()) {
            die("No translations available\n");
        }

        $translationWriter->save();
        echo "Translations updated\n";
    ';

    return 0;
}
#
################################

################################
# fetch files from oTrance, update the files and create a pull request
#
function updateLanguageFiles() {

    pluginsWithTranslations=(`showPluginsWithTranslations`);

    if [ "$#" -eq 1 ]; then
        pluginName=${1};

        if [[ ! ${pluginsWithTranslations[@]} =~ ${pluginName} ]]; then
            echo "${pluginName} does not exist or has no own language files"; exit;
        fi;

        echo "Starting to update language files for plugin ${pluginName}"
    fi

    mergeBranchWithMaster;
    fetchTranslationsFromOTrance;

    existingLanguages=(`showAvailableLanguageCodes`);
    availableFiles=(`ls ${DOWNLOADPATH} | grep "\.json"`);

    for i in "${availableFiles[@]}"; do
        # update translation file
        if [[ ! ${existingLanguages[@]} =~ ${i:0:-5} ]]; then
            echo "language ${i:0:-5} does not exits";
        else
            setTranslationsForLanguage ${i:0:-5} ${DOWNLOADPATH}/${i};
        fi;
    done;

    commitLanguageFiles;
    createPullRequest;
    git checkout master > /dev/null 2>&1
}
#
################################


################################
# prints the help
#
function showHelp() {

    echo "
PIWIK Translation Tool Usage:
${0} COMMAND
Available Commands:
    - languagenames|ln      shows available language names
    - languagecodes|lc      shows available language codes
    - plugintranslations|pt shows all plugins that have own translation files
    - up [PluginName]       updates the language files from oTrance and creates a pull request
                            if [PlguinName] is provided, language files for the plugin are updated
    - fetch                 fetches translations files from oTrance to tmp/oTrance
    - help|usage            shows tihs help screen"
}
#
################################

COMMAND=${1}

case ${COMMAND} in
    ln)             showAvailableLanguageName;;
    languagenames)  showAvailableLanguageName;;
    lc)             showAvailableLanguageCodes;;
    languagecodes)  showAvailableLanguageCodes;;
    pt)             showPluginsWithTranslations;;
    plugintranslations) showPluginsWithTranslations;;
    up)             updateLanguageFiles ${2};;
    fetch)          fetchTranslationsFromOTrance;;
    *)              showHelp
esac