// Copyright 2015 Google Inc. All rights reserved.
//
// 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.

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.util.ArrayList;
import java.util.List;

/**
 * A {@code ClassVisitor} that checks that ijar did its job.
 */
final class StripVerifyingVisitor extends ClassVisitor {
  public List<String> errors = new ArrayList<String>();
  private String className;

  public StripVerifyingVisitor() {
    super(Opcodes.ASM4);
  }

  @Override public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    className = name;
    if ((access & Opcodes.ACC_PRIVATE) != 0) {
      errors.add(String.format("Private class found %s", className));
    }
  }

  @Override public void visitSource(String source, String debug) {
    errors.add(String.format("Source entry found %s %s", source, debug));
  }

  @Override public void visitOuterClass(String owner, String name, String desc) {
    // Always okay.
  }

  @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    // Always okay.
    return null;
  }

  @Override public void visitAttribute(Attribute attr) {
    // Just assume this is okay.
  }

  @Override public void visitInnerClass(
      String name,
      String outerName,
      String innerName,
      int access) {
    // Always okay
    // TODO(bazel-team): verify removal of leftover inner classes once implemented
    // TODO(bazel-team): verify removal of private inner classes once implemented
  }

  @Override public FieldVisitor visitField(
      int access,
      String name,
      String desc,
      String signature,
      Object value) {
    if ((access & Opcodes.ACC_PRIVATE) != 0) {
      errors.add(String.format("Private field %s found in %s", name, className));
    }
    // We need to go deeper.
    return new StripVerifyingFieldVisitor(errors, className, name);
  }

  @Override public MethodVisitor visitMethod(
      int access,
      String name,
      String desc,
      String signature,
      String[] exceptions) {
    if ((access & Opcodes.ACC_PRIVATE) != 0) {
      errors.add(String.format("Private method %s found in %s", name, className));
    }
    // We need to go deeper.
    return new StripVerifyingMethodVisitor(errors, className, name);
  }

  @Override public void visitEnd() {
    // Always okay.
  }

  private static class StripVerifyingFieldVisitor extends FieldVisitor {
    private final List<String> errors;
    private final String className;
    private final String fieldName;

    StripVerifyingFieldVisitor(List<String> errors, String className, String fieldName) {
      super(Opcodes.ASM4);
      this.errors = errors;
      this.className = className;
      this.fieldName = fieldName;
    }

    @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      // Always okay.
      return null;
    }

    @Override public void visitAttribute(Attribute attr) {
      // Just assume this is okay.
    }

    @Override public void visitEnd() {
      // Always okay.
    }
  }

  private static class StripVerifyingMethodVisitor extends MethodVisitor {
    private final List<String> errors;
    private final String className;
    private final String methodName;

    StripVerifyingMethodVisitor(List<String> errors, String className, String methodName) {
      super(Opcodes.ASM4);
      this.errors = errors;
      this.className = className;
      this.methodName = methodName;
    }

    @Override public AnnotationVisitor visitAnnotationDefault() {
      // Always okay.
      return null;
    }

    @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      // Always okay.
      return null;
    }

    @Override public AnnotationVisitor visitParameterAnnotation(
        int parameter,
        String desc,
        boolean visible) {
      // Always okay.
      return null;
    }

    @Override public void visitAttribute(Attribute attr) {
      // Just assume this is okay.
    }

    @Override public void visitCode() {
      errors.add(String.format("Code found for method %s of %s", methodName, className));
    }

    @Override public void visitEnd() {}

    // We ignore all details about code segments. Presumably we already logged an error about code
    // existing at all.

    @Override public void visitFrame(
        int type,
        int nLocal,
        Object[] local,
        int nStack,
        Object[] stack) {}

    @Override public void visitInsn(int opcode) {}

    @Override public void visitIntInsn(int opcode, int operand) {}

    @Override public void visitVarInsn(int opcode, int var) {}

    @Override public void visitTypeInsn(int opcode, String type) {}

    @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) {}

    @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) {}

    @Override public void visitJumpInsn(int opcode, Label label) {}

    @Override public void visitLabel(Label label) {}

    @Override public void visitLdcInsn(Object cst) {}

    @Override public void visitIincInsn(int var, int increment) {}

    @Override public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {}

    @Override public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {}

    @Override public void visitMultiANewArrayInsn(String desc, int dims) {}

    @Override public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {}

    @Override public void visitLocalVariable(
        String name,
        String desc,
        String signature,
        Label start,
        Label end,
        int index) {}

    @Override public void visitLineNumber(int line, Label start) {}

    @Override public void visitMaxs(int maxStack, int maxLocals) {}
  }
}
