package com.maniu.annotation_compiler;


import com.google.auto.service.AutoService;
import com.maniu.annotation.BindPath;

import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

/**
 * 拿到标记了的Activity 生成代码
 */
@AutoService(Processor.class)   //注册了注解处理器
public class AnnotationCompiler extends AbstractProcessor {

    //创建一个生成java文件的对象
    Filer filer;


    //重写三个方法
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        //processingEnvironment这个对象是注解处理器父类的一个工具类
        filer = processingEnvironment.getFiler();
    }

    /**
     * 声明注解处理器支持的java版本
     * @return
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return processingEnv.getSourceVersion();
    }

    /**
     * 声明这个注解处理器要识别的注解有哪些
     * @return
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new HashSet<>();
        types.add(BindPath.class.getCanonicalName());
        return types;
    }

    /**
     * 是核心方法
     * @param set
     * @param roundEnvironment
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        //类节点TypeElement
        //方法节点 ExecutableElement
        //获取到当前模块中用到了BindPath注解的Activity的类对象（类节点）
        Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(BindPath.class);
        Map<String,String> map = new HashMap<>();
        //遍历整个某块中用到了bindPath注解的节点
        for (Element element : elementsAnnotatedWith) {
            TypeElement typeElement = (TypeElement) element;
            //获取到Activity上面的BindPath的注解
            BindPath annotation = typeElement.getAnnotation(BindPath.class);
            //获取到注解里面带的值 中间容器map的Activity所对应的key
            String key = annotation.value();
            //获取到包名加类名
            Name activityName = typeElement.getQualifiedName();
            map.put(key,activityName+".class");
        }
        //写文件
        if(map.size()>0){
            Writer writer = null;
            //需要生成文件的类名  让类名不重复
            String activityName = "ActivityUtil"+System.currentTimeMillis();

            try {
                //生成一个java文件
                JavaFileObject sourceFile = filer.createSourceFile(
                        "com.maniu.util." + activityName);
                //从生产的这个文件开始写
                writer = sourceFile.openWriter();
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append("package com.maniu.util;\n");
                stringBuffer.append("import com.maniu.arouter.ARouter;\n" +
                        "import com.maniu.arouter.IRouter;\n" +
                        "\n" +
                        "public class "+activityName+" implements IRouter {\n" +
                        "    @Override\n" +
                        "    public void putActivity() {\n");
                Iterator<String> iterator = map.keySet().iterator();
                while (iterator.hasNext()){
                    String key = iterator.next();
                    String className = map.get(key);
                    stringBuffer.append("ARouter.getInstance().addActivity(\""+key+"\","+
                            className+");\n");
                }
                stringBuffer.append("\n}\n}");
                writer.write(stringBuffer.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(writer !=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }


        }
        //APT 节点
        //获取到当前模块用到了BindPath的节点
        //TypeElement 类节点
        //ExecutableElement 方法节点
        //VariableElement 成员变量的节点

        return false;
    }


}
