// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static String capitalize(String s) {
//   if (s.length() == 0) {
//     return s;
//   }
//   return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static void error(String msg) {
//   S_INSTANCE.messager.printMessage(Diagnostic.Kind.ERROR, msg);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static Types getTypes() {
//   return S_INSTANCE.types;
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isArrayList(TypeMirror mirror) {
//   // XXX 类型擦除后的 ArrayList<T> 类不能等价于 ArrayList，所以不能用 isSame 判断
//   return S_INSTANCE.types.isAssignable(getTypes().erasure(mirror), S_INSTANCE.arrayList);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isBundle(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.bundle);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isCharSequence(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.charSequence);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isParcelable(TypeMirror mirror, boolean same) {
//   if (same) {
//     return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.parcelable);
//   } else {
//     return S_INSTANCE.types.isAssignable(mirror, S_INSTANCE.parcelable);
//   }
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isSerializable(TypeMirror mirror, boolean same) {
//   if (same) {
//     return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.serializable);
//   } else {
//     return S_INSTANCE.types.isAssignable(mirror, S_INSTANCE.serializable);
//   }
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isString(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.string);
// }


import com.squareup.javapoet.MethodSpec;
import java.util.List;
import java.util.Objects;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.SimpleTypeVisitor8;
import static info.dourok.compiler.EasyUtils.capitalize;
import static info.dourok.compiler.EasyUtils.error;
import static info.dourok.compiler.EasyUtils.getTypes;
import static info.dourok.compiler.EasyUtils.isArrayList;
import static info.dourok.compiler.EasyUtils.isBundle;
import static info.dourok.compiler.EasyUtils.isCharSequence;
import static info.dourok.compiler.EasyUtils.isParcelable;
import static info.dourok.compiler.EasyUtils.isSerializable;
import static info.dourok.compiler.EasyUtils.isString;

  @Override
  public void writeSetter(MethodSpec.Builder paper) {
    paper.addStatement("getIntent().putExtra($S,$L)", getKey(), getDisplayName());
  }

  @Override
  public void doWriteRestore(MethodSpec.Builder paper, String activityName, String bundleName) {
    if (isSubTypeOfParcelableOrSerializable()) {
      paper.addStatement(
          "$L.$L = ($T) $L.get$L($S)",
          activityName,
          getName(),
          parameter,
          bundleName,
          prefix,
          getKey());
    } else {
      paper.addStatement(
          "$L.$L = $L.get$L($S)", activityName, getName(), bundleName, prefix, getKey());
    }
  }

  @Override
  public void doWriteSave(MethodSpec.Builder paper, String activityName, String bundleName) {
    paper.addStatement("$L.put$L($S,$L.$L)", bundleName, prefix, getKey(), activityName, getName());
  }

  private boolean isSubTypeOfParcelableOrSerializable() {
    return (Objects.equals(prefix, "Parcelable") && !isParcelable(getType(), true))
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static String capitalize(String s) {
//   if (s.length() == 0) {
//     return s;
//   }
//   return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static void error(String msg) {
//   S_INSTANCE.messager.printMessage(Diagnostic.Kind.ERROR, msg);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static Types getTypes() {
//   return S_INSTANCE.types;
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isArrayList(TypeMirror mirror) {
//   // XXX 类型擦除后的 ArrayList<T> 类不能等价于 ArrayList，所以不能用 isSame 判断
//   return S_INSTANCE.types.isAssignable(getTypes().erasure(mirror), S_INSTANCE.arrayList);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isBundle(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.bundle);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isCharSequence(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.charSequence);
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isParcelable(TypeMirror mirror, boolean same) {
//   if (same) {
//     return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.parcelable);
//   } else {
//     return S_INSTANCE.types.isAssignable(mirror, S_INSTANCE.parcelable);
//   }
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isSerializable(TypeMirror mirror, boolean same) {
//   if (same) {
//     return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.serializable);
//   } else {
//     return S_INSTANCE.types.isAssignable(mirror, S_INSTANCE.serializable);
//   }
// }
// 
// Path: compiler/src/main/java/info/dourok/compiler/EasyUtils.java
// public static boolean isString(TypeMirror mirror) {
//   return S_INSTANCE.types.isSameType(mirror, S_INSTANCE.string);
// }


// Path: compiler/src/main/java/info/dourok/compiler/parameter/BundleWriter.java
import com.squareup.javapoet.MethodSpec;
import java.util.List;
import java.util.Objects;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.SimpleTypeVisitor8;
import static info.dourok.compiler.EasyUtils.capitalize;
import static info.dourok.compiler.EasyUtils.error;
import static info.dourok.compiler.EasyUtils.getTypes;
import static info.dourok.compiler.EasyUtils.isArrayList;
import static info.dourok.compiler.EasyUtils.isBundle;
import static info.dourok.compiler.EasyUtils.isCharSequence;
import static info.dourok.compiler.EasyUtils.isParcelable;
import static info.dourok.compiler.EasyUtils.isSerializable;
import static info.dourok.compiler.EasyUtils.isString;


  @Override
  public void writeSetter(MethodSpec.Builder paper) {
    paper.addStatement("getIntent().putExtra($S,$L)", getKey(), getDisplayName());
  }

  @Override
  public void doWriteRestore(MethodSpec.Builder paper, String activityName, String bundleName) {
    if (isSubTypeOfParcelableOrSerializable()) {
      paper.addStatement(
          "$L.$L = ($T) $L.get$L($S)",
          activityName,
          getName(),
          parameter,
          bundleName,
          prefix,
          getKey());
    } else {
      paper.addStatement(
          "$L.$L = $L.get$L($S)", activityName, getName(), bundleName, prefix, getKey());
    }
  }

  @Override
  public void doWriteSave(MethodSpec.Builder paper, String activityName, String bundleName) {
    paper.addStatement("$L.put$L($S,$L.$L)", bundleName, prefix, getKey(), activityName, getName());
  }

  private boolean isSubTypeOfParcelableOrSerializable() {
    return (Objects.equals(prefix, "Parcelable") && !isParcelable(getType(), true))
        || (Objects.equals(prefix, "Serializable")) && (!isSerializable(getType(), true));