package se.vidstige.jadb.managers;

import se.vidstige.jadb.JadbDevice;
import se.vidstige.jadb.JadbException;
import se.vidstige.jadb.RemoteFile;
import se.vidstige.jadb.Stream;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * Java interface to package manager. Launches package manager through jadb
 */
public class PackageManager {
    private final JadbDevice device;

    public PackageManager(JadbDevice device) {
        this.device = device;
    }

    public List<Package> getPackages() throws IOException, JadbException {
        ArrayList<Package> result = new ArrayList<Package>();
        BufferedReader input = null;
        try {
            input = new BufferedReader(new InputStreamReader(device.executeShell("pm", "list", "packages"), Charset.forName("UTF-8")));
            String line;
            while ((line = input.readLine()) != null) {
                final String prefix = "package:";
                if (line.startsWith(prefix)) {
                    result.add(new Package(line.substring(prefix.length())));
                }
            }
        } finally {
            if (input != null) input.close();
        }
        return result;
    }

    private String getErrorMessage(String operation, String target, String errorMessage) {
        return "Could not " + operation + " " + target + ": " + errorMessage;
    }

    private void verifyOperation(String operation, String target, String result) throws JadbException {
        if (!result.contains("Success")) throw new JadbException(getErrorMessage(operation, target, result));
    }

    public void install(File apkFile) throws IOException, JadbException {
        RemoteFile remote = new RemoteFile("/sdcard/tmp/" + apkFile.getName());
        device.push(apkFile, remote);
        InputStream s = device.executeShell("pm", "install", Bash.quote(remote.getPath()));
        String result = Stream.readAll(s, Charset.forName("UTF-8"));
        // TODO: Remove remote file
        verifyOperation("install", apkFile.getName(), result);
    }

    public void forceInstall(File apkFile) throws IOException, JadbException {
        RemoteFile remote = new RemoteFile("/sdcard/tmp/" + apkFile.getName());
        device.push(apkFile, remote);
        InputStream s = device.executeShell("pm", "install","-r", Bash.quote(remote.getPath()));
        String result = Stream.readAll(s, Charset.forName("UTF-8"));
        // TODO: Remove remote file
        s=device.executeShell("rm", "-f",Bash.quote(remote.getPath()));
        Stream.readAll(s, Charset.forName("UTF-8"));
        verifyOperation("install", apkFile.getName(), result);
    }

    public void uninstall(Package name) throws IOException, JadbException {
        InputStream s = device.executeShell("pm", "uninstall", name.toString());
        String result = Stream.readAll(s, Charset.forName("UTF-8"));
        verifyOperation("uninstall", name.toString(), result);
    }

    public void launch(Package name) throws IOException, JadbException {
        InputStream s = device.executeShell("monkey", "-p", name.toString(), "-c", "android.intent.category.LAUNCHER", "1");
    }
}

@@ -1655,32 +1655,53 @@
 all(File apkFile
+,boolean forceInstall
 ) throws IOExcep
@@ -1853,33 +1853,73 @@
    InputStream s
- 
+;%0A        if(forceInstall)%7B%0A            s
 = device.execute
@@ -1940,16 +1940,22 @@
 nstall%22,
+ %22-r%22,
  Bash.qu
@@ -1990,394 +1990,28 @@
     
-String result = Stream.readAll(s, Charset.forName(%22UTF-8%22));%0A        // TODO: Remove remote file%0A        verifyOperation(%22install%22, apkFile.getName(), result);%0A    %7D%0A%0A    public void forceInstall(File apkFile) throws IOException, JadbException %7B%0A        RemoteFile remote = new RemoteFile(%22/sdcard/tmp/%22 + apkFile.getName());%0A        device.push(apkFile, remote);%0A        InputStream s 
+%7Delse%7B%0A            s
 = de
@@ -2044,21 +2044,16 @@
 nstall%22,
-%22-r%22,
  Bash.qu
@@ -2068,32 +2068,42 @@
 te.getPath()));%0A
+        %7D%0A
         String r
@@ -2159,44 +2159,8 @@
 ));%0A
-        // TODO: Remove remote file%0A
     
@@ -2342,32 +2342,33 @@
 result);%0A    %7D%0A%0A
+%0A
     public void 

add forceInstall for application already exist add a way to remove installed apk