/*
 * Copyright (C) 2014 AChep@xda <artemchep@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

import groovy.swing.SwingBuilder
import org.apache.commons.codec.binary.Base64

import java.text.SimpleDateFormat

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        //noinspection GradleDynamicVersion
        classpath 'org.robolectric:robolectric-gradle-plugin:0.14.+'
        //noinspection GradleDynamicVersion
        classpath 'com.android.tools.build:gradle:1.0.+'
        classpath 'commons-codec:commons-codec:1.10'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'robolectric'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 21
    buildToolsVersion '21.1.2'

    lintOptions {
        checkReleaseBuilds true
        abortOnError false
    }

    dexOptions {
        incremental false
    }

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 21
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    sourceSets {
        main {
            aidl.srcDirs = ['src/main/java']
        }
    }

    //noinspection GroovyAssignabilityCheck
    SimpleDateFormat timeStampFormat = new SimpleDateFormat(
            "EEE MMMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH); // Don't change it!
    String timeStamp = timeStampFormat.format(Calendar.getInstance().getTime());

    String key = System.getenv("HEADSUP_GOOGLE_PLAY_PUBLIC_KEY");
    if (key == null) key = "this-is-a-debug-build-blank-key";
    String keySalt = UUID.randomUUID().toString();
    String keyEncrypted = encryptPublicKey(key, keySalt);

    // Google Play key is very important and better to check it twice
    // then to get a billion of Force Close reports.
    println "- - - - - - - - - - - -"
    println "\u001B[36m\u001B[1mGOOGLE_PLAY_PUBLIC_KEY\u001B[0m: " + key
    println "- - - - - - - - - - - -"

    signingConfigs {
        release {
            storeFile file(System.getenv("HEADSUP_SIGN_STORE_FILE") + "")
            keyAlias System.getenv("HEADSUP_SIGN_KEY_ALIAS") + ""
            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword 'empty'
            keyPassword 'empty'
        }
    }

    buildTypes {
        debug {
            versionNameSuffix '-debug'
            buildConfigField "boolean", "MY_DEBUG", "true"
            buildConfigField "String", "MY_TIME_STAMP", "\"" + timeStamp + "\""
            buildConfigField "String", "MY_GOOGLE_PLAY_PUBLIC_KEY", "\"" + keyEncrypted + "\""
            buildConfigField "String", "MY_GOOGLE_PLAY_PUBLIC_KEY_SALT", "\"" + keySalt + "\""
        }
        release {
            zipAlignEnabled true
            minifyEnabled true
            proguardFile 'proguard-rules.txt'
            signingConfig signingConfigs.release

            buildConfigField "boolean", "MY_DEBUG", "false"
            buildConfigField "String", "MY_TIME_STAMP", "\"" + timeStamp + "\""
            buildConfigField "String", "MY_GOOGLE_PLAY_PUBLIC_KEY", "\"" + keyEncrypted + "\""
            buildConfigField "String", "MY_GOOGLE_PLAY_PUBLIC_KEY_SALT", "\"" + keySalt + "\""
        }
    }

    productFlavors {
        //noinspection GroovyMissingReturnStatement
        defaultFlavor {}
        //noinspection GroovyMissingReturnStatement
        releaseFlavor {}
    }
}

// Visit for more info:
// https://github.com/robolectric/robolectric-gradle-plugin
robolectric {
    ignoreFailures true

    // Specify max number of processes (default is 1)
    maxParallelForks = 4

    // Listen to the test execution results
    afterTest { descriptor, result ->
        println "Executing test for ${descriptor.name} with result: ${result.resultType}"
    }
}

dependencies {
    // Other libraries.
    //noinspection GradleDynamicVersion
    compile 'com.larswerkman:HoloColorPicker:1.4'
    //noinspection GradleDynamicVersion
    compile 'me.grantland:autofittextview:0.2.+'
    //noinspection GradleDynamicVersion
    compile 'org.solovyev.android:checkout:0.6.+@aar'
    provided fileTree(dir: 'src/main/libs', include: ['XposedBridgeApi*.jar'])
    compile fileTree(dir: 'src/main/libs', include: ['*.jar'], exclude: ['XposedBridgeApi*'])

    // Android support libs.
    compile('com.android.support:palette-v7:+')
    compile('com.android.support:appcompat-v7:21.+')
    compile('com.android.support:recyclerview-v7:21.+')
    compile('com.android.support:support-v13:21.+')

    // Robolectric tests.
    androidTestCompile('junit:junit:4.11')
    androidTestCompile('org.robolectric:robolectric:2.3') {
        exclude module: 'classworlds'
        exclude module: 'commons-logging'
        exclude module: 'httpclient'
        exclude module: 'maven-artifact'
        exclude module: 'maven-artifact-manager'
        exclude module: 'maven-error-diagnostics'
        exclude module: 'maven-model'
        exclude module: 'maven-project'
        exclude module: 'maven-settings'
        exclude module: 'plexus-container-default'
        exclude module: 'plexus-interpolation'
        exclude module: 'plexus-utils'
        exclude module: 'wagon-file'
        exclude module: 'wagon-http-lightweight'
        exclude module: 'wagon-provider-api'
    }
}

project.task('askForPasswords') << {
    def passKeystore = ''
    def passKey = ''
    if (System.console() == null) {
        new SwingBuilder().dialog(
                modal: true,
                title: 'Enter sign config:',
                alwaysOnTop: true,
                resizable: false,
                locationRelativeTo: null,
                pack: true,
                show: true
        ) {
            panel(constraints: BorderLayout.CENTER) {
                tableLayout(cellpadding: 4) {
                    tr {
                        td { label(text: "Keystore password:") }
                        td { passwordField(columns: 20, id: 'inputKeystore') }
                    }
                    tr {
                        td { label(text: "Key password:") }
                        td { passwordField(columns: 20, id: 'inputKey') }
                    }
                }
            }
            panel(constraints: BorderLayout.SOUTH) {
                button(defaultButton: true, text: "OK", actionPerformed: {
                    passKeystore = inputKeystore.password;
                    passKey = inputKey.password;
                    dispose(); // Close dialog
                })
            }
        } // dialog end
    } else {
        Console console = System.console();
        console.printf("\n\n\u001B[36m\u001B[1mSigning config\u001B[0m\n")

        if ("true".equals(System.getenv("HEADSUP_USE_TEST_KEY") + "")
                || "yes".equals(console.readLine("Use default test key [yes/no]: "))) {
            android.signingConfigs.release.storeFile = file("test-key.keystore")
            android.signingConfigs.release.keyAlias = "acdisplay-test-build"
            passKeystore = "FBxBT8KmUPkKnks5"
            passKey = "KBFvGmGgDGh9HyFx"
        } else {
            passKeystore = new String(console.readPassword("Please enter store password: "))
            passKey = new String(console.readPassword("Please enter key password: "))
        }
    }

    if (passKeystore.size() <= 0 || passKey.size() <= 0) {
        throw new InvalidUserDataException("You must enter a password to proceed.")
    }

    android.signingConfigs.release.storePassword = passKeystore
    android.signingConfigs.release.keyPassword = passKey
}

project.configure(project) {
    if (it.hasProperty("android")) {
        tasks.whenTaskAdded { theTask ->
            if ((theTask.name ==~ /package.*Release/)
                    && it.android.hasProperty("signingConfigs")
                    && it.android.signingConfigs.hasProperty("release")) {
                it.android.signingConfigs.release.storePassword = "-"
                it.android.signingConfigs.release.keyPassword = "-"
                theTask.dependsOn "askForPasswords"
            }
        }
    }
}

/**
 * Protects the key from kids, script kiddies and dumbs.
 *
 * @param key the key to encrypt
 * @return encrypted tkey
 */
// Symmetric algorithm used for ciphering/deciphering.
def encryptPublicKey(String key, String salt) {
    String encoded = encryptPublicKeyX(key, salt);
    return Base64.encodeBase64URLSafeString(encoded.getBytes());
}

def encryptPublicKeyX(String key, String salt) {
    final char[] m = key.toCharArray();
    final char[] s = salt.toCharArray();

    final int ml = m.length;
    final int sl = s.length;
    final char[] result = new char[ml];

    for (int i = 0; i < ml; i++) {
        result[i] = (char) (m[i] ^ s[i % sl]);
    }

    return new String(result);
}
