// Path: library/src/main/java/com/sys1yagi/fragmentcreator/FragmentCreator.java
// public abstract class FragmentCreator {
// 
//     public static void checkRequire(Object param, String paramName) {
//         if (param == null) {
//             throw new UnsupportedTypeException(paramName + "　is required.");
//         }
//     }
// 
//     public static <T> void isValid(T param, Validator<T> validator) {
//         if (!validator.isValid(param)) {
//             //TODO rich message
//             throw new InvalidParameterException(param.getClass().getName() + " is invalid.");
//         }
//     }
// }
// 
// Path: processor/src/main/java/com/sys1yagi/fragmentcreator/model/FragmentCreatorModel.java
// public class FragmentCreatorModel {
// 
//     private TypeElement element;
// 
//     private String packageName;
// 
//     private String originalClassName;
// 
//     private String creatorClassName;
// 
//     private List<VariableElement> argsList = new ArrayList<>();
// 
//     public FragmentCreatorModel(TypeElement element, Elements elementUtils) {
//         this.element = element;
//         this.packageName = getPackageName(elementUtils, element);
//         this.originalClassName = getClassName(element, packageName);
//         this.creatorClassName = originalClassName.concat("Creator");
//         findAnnotations(element);
//     }
// 
//     private void findAnnotations(Element element) {
//         for (Element enclosedElement : element.getEnclosedElements()) {
//             findAnnotations(enclosedElement);
// 
//             Args args = enclosedElement.getAnnotation(Args.class);
//             if (args != null) {
//                 this.argsList.add((VariableElement) enclosedElement);
//             }
//         }
//     }
// 
//     private String getPackageName(Elements elementUtils, TypeElement type) {
//         return elementUtils.getPackageOf(type).getQualifiedName().toString();
//     }
// 
//     private static String getClassName(TypeElement type, String packageName) {
//         int packageLen = packageName.length() + 1;
//         return type.getQualifiedName().toString().substring(packageLen).replace('.', '$');
//     }
// 
//     public TypeElement getElement() {
//         return element;
//     }
// 
//     public String getPackageName() {
//         return packageName;
//     }
// 
//     public String getOriginalClassName() {
//         return originalClassName;
//     }
// 
//     public String getCreatorClassName() {
//         return creatorClassName;
//     }
// 
//     public List<VariableElement> getArgsList() {
//         return argsList;
//     }
// }


import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import com.sys1yagi.fragmentcreator.FragmentCreator;
import com.sys1yagi.fragmentcreator.model.FragmentCreatorModel;
import java.io.IOException;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Modifier;
package com.sys1yagi.fragmentcreator.writer;




public class FragmentCreatorWriter {

    FragmentCreatorModel model;

    ProcessingEnvironment environment;

    public FragmentCreatorWriter(ProcessingEnvironment environment, FragmentCreatorModel model) {
        this.environment = environment;
        this.model = model;
    }

    public void write(Filer filer) throws IOException {
        FragmentCreatorBuilderGenerator fragmentCreatorBuilderGenerator =
                new FragmentCreatorBuilderGenerator(environment);
        FragmentCreatorReadGenerator fragmentCreatorReadGenerator = new FragmentCreatorReadGenerator(environment);

        TypeSpec.Builder classBuilder = createClassBuilder();

        classBuilder.addType(fragmentCreatorBuilderGenerator.create(model));
        classBuilder.addMethod(fragmentCreatorReadGenerator.createReadMethod(model));
        classBuilder.addMethod(fragmentCreatorBuilderGenerator.createBuilderNewBuilder(model, model.getArgsList()));

        TypeSpec outClass = classBuilder.build();
        JavaFile.builder(model.getPackageName(), outClass)
                .addFileComment("This file was generated by fragment-creator. Do not modify!")
                .build()
                .writeTo(filer);
    }

    private TypeSpec.Builder createClassBuilder(){
        TypeSpec.Builder classBuilder =TypeSpec.classBuilder(model.getCreatorClassName());
        classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
// Path: library/src/main/java/com/sys1yagi/fragmentcreator/FragmentCreator.java
// public abstract class FragmentCreator {
// 
//     public static void checkRequire(Object param, String paramName) {
//         if (param == null) {
//             throw new UnsupportedTypeException(paramName + "　is required.");
//         }
//     }
// 
//     public static <T> void isValid(T param, Validator<T> validator) {
//         if (!validator.isValid(param)) {
//             //TODO rich message
//             throw new InvalidParameterException(param.getClass().getName() + " is invalid.");
//         }
//     }
// }
// 
// Path: processor/src/main/java/com/sys1yagi/fragmentcreator/model/FragmentCreatorModel.java
// public class FragmentCreatorModel {
// 
//     private TypeElement element;
// 
//     private String packageName;
// 
//     private String originalClassName;
// 
//     private String creatorClassName;
// 
//     private List<VariableElement> argsList = new ArrayList<>();
// 
//     public FragmentCreatorModel(TypeElement element, Elements elementUtils) {
//         this.element = element;
//         this.packageName = getPackageName(elementUtils, element);
//         this.originalClassName = getClassName(element, packageName);
//         this.creatorClassName = originalClassName.concat("Creator");
//         findAnnotations(element);
//     }
// 
//     private void findAnnotations(Element element) {
//         for (Element enclosedElement : element.getEnclosedElements()) {
//             findAnnotations(enclosedElement);
// 
//             Args args = enclosedElement.getAnnotation(Args.class);
//             if (args != null) {
//                 this.argsList.add((VariableElement) enclosedElement);
//             }
//         }
//     }
// 
//     private String getPackageName(Elements elementUtils, TypeElement type) {
//         return elementUtils.getPackageOf(type).getQualifiedName().toString();
//     }
// 
//     private static String getClassName(TypeElement type, String packageName) {
//         int packageLen = packageName.length() + 1;
//         return type.getQualifiedName().toString().substring(packageLen).replace('.', '$');
//     }
// 
//     public TypeElement getElement() {
//         return element;
//     }
// 
//     public String getPackageName() {
//         return packageName;
//     }
// 
//     public String getOriginalClassName() {
//         return originalClassName;
//     }
// 
//     public String getCreatorClassName() {
//         return creatorClassName;
//     }
// 
//     public List<VariableElement> getArgsList() {
//         return argsList;
//     }
// }


// Path: processor/src/main/java/com/sys1yagi/fragmentcreator/writer/FragmentCreatorWriter.java
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import com.sys1yagi.fragmentcreator.FragmentCreator;
import com.sys1yagi.fragmentcreator.model.FragmentCreatorModel;
import java.io.IOException;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Modifier;

package com.sys1yagi.fragmentcreator.writer;




public class FragmentCreatorWriter {

    FragmentCreatorModel model;

    ProcessingEnvironment environment;

    public FragmentCreatorWriter(ProcessingEnvironment environment, FragmentCreatorModel model) {
        this.environment = environment;
        this.model = model;
    }

    public void write(Filer filer) throws IOException {
        FragmentCreatorBuilderGenerator fragmentCreatorBuilderGenerator =
                new FragmentCreatorBuilderGenerator(environment);
        FragmentCreatorReadGenerator fragmentCreatorReadGenerator = new FragmentCreatorReadGenerator(environment);

        TypeSpec.Builder classBuilder = createClassBuilder();

        classBuilder.addType(fragmentCreatorBuilderGenerator.create(model));
        classBuilder.addMethod(fragmentCreatorReadGenerator.createReadMethod(model));
        classBuilder.addMethod(fragmentCreatorBuilderGenerator.createBuilderNewBuilder(model, model.getArgsList()));

        TypeSpec outClass = classBuilder.build();
        JavaFile.builder(model.getPackageName(), outClass)
                .addFileComment("This file was generated by fragment-creator. Do not modify!")
                .build()
                .writeTo(filer);
    }

    private TypeSpec.Builder createClassBuilder(){
        TypeSpec.Builder classBuilder =TypeSpec.classBuilder(model.getCreatorClassName());
        classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
        ClassName superClassName = ClassName.get(FragmentCreator.class);