//
// monotouch-maven-plugin - builds and deploys MonoTouch projects
// http://github.com/samskivert/monotouch-maven-plugin/blob/master/LICENSE

package com.samskivert;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.plexus.util.cli.Commandline;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;

/**
 * Goal which builds and installs the project on an iOS device.
 */
@Mojo(name="deploy-device", defaultPhase=LifecyclePhase.NONE,
    requiresDependencyResolution=ResolutionScope.COMPILE_PLUS_RUNTIME)
public class DeployDeviceMojo extends BuildDeviceMojo
{
    /**
     * Indicates whether the app should be launched after it is installed.
     */
    @Parameter(property="device.launch", defaultValue="true")
    public boolean launch;

    public void execute () throws MojoExecutionException {
        super.execute();

        // make a note of the mdtool build output directory
        File buildDir = new File(_project.getBuild().getDirectory() +
                                 File.separator + DEVICE + File.separator + build);

        // determine the name and path to our app directory
        String appName = resolveAppName();
        File appDir = new File(buildDir, appName);

        // install it to the device, if desired
        Commandline dcmd = newCommandline(mtouchPath.getPath());
        dcmd.createArg().setValue("--installdev=" + appDir.getAbsolutePath());
        getLog().debug("MTOUCH: " + dcmd);
        invoke("mtouch", dcmd);

        // launch it on the device, if desired
        if (launch) {
            // read in the .xcent file to obtain the app id
            File xcent = new File(buildDir, appName.replaceAll(".app$", ".xcent"));
            Map<String,String> info = parsePlist(xcent);
            String appId = info.get("application-identifier");
            if (appId == null) throw new MojoExecutionException(
                "Failed to extract app-id from " + xcent.getPath());
            // strip off the Apple gobbledygook from the front of the app id
            appId = appId.replaceAll("^[A-Z0-9]+\\.", "");

            // and run mtouch to launch the app
            Commandline lcmd = newCommandline(mtouchPath.getPath());
            lcmd.createArg().setValue("--launchdev=" + appId);
            getLog().debug("MTOUCH: " + lcmd);
            invoke("mtouch", lcmd);
        }
    }

    // this only matches simple <key>/<string> pairs, but that suffices for our purposes
    protected Map<String,String> parsePlist (File file) throws MojoExecutionException {
        try {
            Map<String,String> info = new HashMap<String,String>();
            Pattern pat = Pattern.compile("<(.*)>(.*)</(.*)>");
            BufferedReader in = new BufferedReader(new FileReader(file));
            String line;
            String prevKey = null;
            while ((line = in.readLine()) != null) {
                Matcher m = pat.matcher(line.trim());
                if (m.matches()) {
                    String type = m.group(1);
                    String value = m.group(2);
                    if (prevKey == null && type.equals("key")) prevKey = value;
                    else if (prevKey != null && type.equals("string")) info.put(prevKey, value);
                    else prevKey = null;
                }
            }
            return info;
        } catch (IOException ioe) {
            throw new MojoExecutionException("Failed to parse " + file.getPath(), ioe);
        }
    }

    protected static final String DEVICE = "iPhone";
}

@@ -1157,16 +1157,275 @@
 aunch;%0A%0A
+    /**%0A     * Indicates where the build is output. By default, this is calculated using the provided%0A     * %7B@link #solution%7D and %7B@link #build%7D. E.g. %7B@code bin/iPhone/Debug%7D.%0A     */%0A    @Parameter(property=%22mtouch.output.dir%22)%0A    public File outputDir;%0A%0A
     publ
@@ -1513,147 +1513,175 @@
     
-// make a note of th
+if (outputDir == null) %7B%0A            // this is wher
 e m
-d
 to
-ol build output directory%0A        File buildDir = new File(_project.getBuild().getDirectory() +%0A                 
+uch normally places binaries%0A            outputDir = new File(solution.getParent() + File.separator + %22bin%22 +%0A
     
@@ -1742,16 +1742,26 @@
  build);
+%0A        %7D
 %0A%0A      
@@ -1880,37 +1880,38 @@
 pDir = new File(
-build
+output
 Dir, appName);%0A%0A
@@ -2341,21 +2341,22 @@
 ew File(
-build
+output
 Dir, app

Allow projects to be nested.