/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.compatibility.common.generator;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.kxml2.io.KXmlSerializer;

public class ManifestGenerator {

    private static final String DEFAULT_MIN_SDK = "8";

    private static final String USAGE =
            "Usage: manifest-generator -n NAME -p PACKAGE_NAME -o OUTPUT_FILE -i INSTRUMENT_NAME "
                    + "[-s MIN_SDK_VERSION] [-t TARGET_SDK_VERSION] [-r PERMISSION]+ "
                    + "[-a ACTIVITY]+ [-l REQUIRED_LIBRARY]+ [-lo OPTIONAL_LIBRARY]+";
    private static final String MANIFEST = "manifest";
    private static final String USES_SDK = "uses-sdk";
    private static final String USES_PERMISSION = "uses-permission";
    private static final String APPLICATION = "application";
    private static final String INSTRUMENTATION = "instrumentation";
    private static final String ACTIVITY = "activity";
    private static final String USES_LIBRARY = "uses-library";

    public static void main(String[] args) {
        String pkgName = null;
        String instrumentName = null;
        String minSdk = DEFAULT_MIN_SDK;
        String targetSdk = null;
        List<String> permissions = new ArrayList<>();
        List<String> activities = new ArrayList<>();
        List<String> libraries = new ArrayList<>();
        List<String> optionalLibs = new ArrayList<>();
        String output = null;

        for (int i = 0; i < args.length - 1; i++) {
            if (args[i].equals("-p")) {
                pkgName = args[++i];
            } else if (args[i].equals("-a")) {
                activities.add(args[++i]);
            } else if (args[i].equals("-l")) {
                libraries.add(args[++i]);
            } else if (args[i].equals("-lo")) {
                optionalLibs.add(args[++i]);
            } else if (args[i].equals("-o")) {
                output = args[++i];
            } else if (args[i].equals("-i")) {
                instrumentName = args[++i];
            } else if (args[i].equals("-r")) {
                permissions.add(args[++i]);
            } else if (args[i].equals("-s")) {
                minSdk = args[++i];
            } else if (args[i].equals("-t")) {
                targetSdk = args[++i];
            }
        }

        if (pkgName == null) {
            error("Missing package name");
        } else if (instrumentName == null) {
            error("Missing instrumentation name");
        } else if (activities.isEmpty()) {
            error("No activities");
        } else if (output == null) {
            error("Missing output file");
        }

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(output);
            generate(
                    out,
                    pkgName,
                    instrumentName,
                    minSdk,
                    targetSdk,
                    permissions,
                    activities,
                    libraries,
                    optionalLibs);
        } catch (Exception e) {
            System.err.println("Couldn't create manifest file");
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    // Ignore
                }
            }
        }
    }

    /*package*/ static void generate(
            OutputStream out,
            String pkgName,
            String instrumentName,
            String minSdk,
            String targetSdk,
            List<String> permissions,
            List<String> activities,
            List<String> libraries,
            List<String> optionalLibs)
            throws Exception {
        final String ns = null;
        KXmlSerializer serializer = new KXmlSerializer();
        serializer.setOutput(out, "UTF-8");
        serializer.startDocument("UTF-8", true);
        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
        serializer.startTag(ns, MANIFEST);
        serializer.attribute(ns, "xmlns:android", "http://schemas.android.com/apk/res/android");
        serializer.attribute(ns, "package", pkgName);
        serializer.startTag(ns, USES_SDK);
        serializer.attribute(ns, "android:minSdkVersion", minSdk);
        if (targetSdk != null) {
            serializer.attribute(ns, "android:targetSdkVersion", targetSdk);
        }
        serializer.endTag(ns, USES_SDK);
        for (String permission : permissions) {
            serializer.startTag(ns, USES_PERMISSION);
            serializer.attribute(ns, "android:name", permission);
            serializer.endTag(ns, USES_PERMISSION);
        }
        serializer.startTag(ns, APPLICATION);
        for (String library : libraries) {
            serializer.startTag(ns, USES_LIBRARY);
            serializer.attribute(ns, "android:name", library);
            serializer.endTag(ns, USES_LIBRARY);
        }
        for (String optionalLib : optionalLibs) {
            serializer.startTag(ns, USES_LIBRARY);
            serializer.attribute(ns, "android:name", optionalLib);
            serializer.attribute(ns, "android:required", "false");
            serializer.endTag(ns, USES_LIBRARY);
        }
        for (String activity : activities) {
            serializer.startTag(ns, ACTIVITY);
            serializer.attribute(ns, "android:name", activity);
            serializer.endTag(ns, ACTIVITY);
        }
        serializer.endTag(ns, APPLICATION);
        serializer.startTag(ns, INSTRUMENTATION);
        serializer.attribute(ns, "android:name", instrumentName);
        serializer.attribute(ns, "android:targetPackage", pkgName);
        serializer.endTag(ns, INSTRUMENTATION);
        serializer.endTag(ns, MANIFEST);
        serializer.endDocument();
        out.flush();
    }

    private static void error(String message) {
        System.err.println(message);
        System.err.println(USAGE);
        System.exit(1);
    }
}
