/*
 * Copyright (C) 2008 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.dx.command.annotool;

import com.android.dx.cf.direct.ClassPathOpener;
import com.android.dx.cf.direct.DirectClassFile;
import com.android.dx.cf.direct.StdAttributeFactory;
import com.android.dx.cf.iface.AttributeList;
import com.android.dx.cf.iface.Attribute;
import com.android.dx.cf.attrib.AttRuntimeInvisibleAnnotations;
import com.android.dx.cf.attrib.BaseAnnotations;
import com.android.dx.cf.attrib.AttRuntimeVisibleAnnotations;
import com.android.dx.util.ByteArray;
import com.android.dx.rop.annotation.Annotation;

import java.io.File;
import java.lang.annotation.ElementType;
import java.util.EnumSet;
import java.util.Arrays;


public class Main {

    private static class InvalidArgumentException extends Exception {
        InvalidArgumentException() {
            super();
        }

        InvalidArgumentException(String s) {
            super(s);
        }
    }

    enum PrintType {
        CLASS,
        INNERCLASS,
        METHOD,
        PACKAGE
    }


    static class Arguments {
        /**
         * from --annotation, dot-seperated classname
         * of annotation to look for
         */
        String aclass;

        /** from --eTypes */
        EnumSet<ElementType> eTypes = EnumSet.noneOf(ElementType.class);

        /** from --print */
        EnumSet<PrintType> printTypes = EnumSet.noneOf(PrintType.class);

        /** remaining positional arguments */
        String[] files;

        Arguments() {
        }

        void parse (String[] argArray) throws InvalidArgumentException {
            for (int i = 0; i < argArray.length; i++) {
                String arg = argArray[i];

                if (arg.startsWith("--annotation=")) {
                    String argParam = arg.substring(arg.indexOf('=') + 1);
                    if (aclass != null) {
                        throw new InvalidArgumentException(
                                "--annotation can only be specified once.");
                    }
                    aclass = argParam.replace('.','/');
                } else if (arg.startsWith("--element=")) {
                    String argParam = arg.substring(arg.indexOf('=') + 1);

                    try {
                        for (String p : argParam.split(",")) {
                            eTypes.add(ElementType.valueOf(p.toUpperCase()));
                        }
                    } catch (IllegalArgumentException ex) {
                        throw new InvalidArgumentException(
                                "invalid --element");
                    }
                } else if (arg.startsWith("--print=")) {
                    String argParam = arg.substring(arg.indexOf('=') + 1);

                    try {
                        for (String p : argParam.split(",")) {
                            printTypes.add(PrintType.valueOf(p.toUpperCase()));
                        }
                    } catch (IllegalArgumentException ex) {
                        throw new InvalidArgumentException("invalid --print");
                    }
                } else {
                    files = new String[argArray.length - i];
                    System.arraycopy(argArray, i, files, 0, files.length);
                    break;
                }
            }

            if (aclass == null) {
                throw new InvalidArgumentException(
                        "--annotation must be specified");
            }

            if (printTypes.isEmpty()) {
                printTypes.add(PrintType.CLASS);
            }

            if (eTypes.isEmpty()) {
                eTypes.add(ElementType.TYPE);
            }

            EnumSet<ElementType> set = eTypes.clone();

            set.remove(ElementType.TYPE);
            set.remove(ElementType.PACKAGE);
            if (!set.isEmpty()) {
                throw new InvalidArgumentException(
                        "only --element parameters 'type' and 'package' "
                                + "supported");
            }
        }
    }

    /**
     * This class is uninstantiable.
     */
    private Main() {
        // This space intentionally left blank.
    }

    public static void main(String[] argArray) {

        final Arguments args = new Arguments();

        try {
            args.parse(argArray);
        } catch (InvalidArgumentException ex) {
            System.err.println(ex.getMessage());

            throw new RuntimeException("usage");
        }

        new AnnotationLister(args).process();
    }
}
