/**
 * Copyright © 2010-2013 Nokia
 *
 * 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 org.jsonschema2pojo.util;

import android.os.Parcel;
import android.os.Parcelable.Creator;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JVar;

public class ParcelableHelper {

    public void addWriteToParcel(JDefinedClass jclass) {
        JMethod method = jclass.method(JMod.PUBLIC, void.class, "writeToParcel");
        JVar dest = method.param(Parcel.class, "dest");
        method.param(int.class, "flags");
        
        for (JFieldVar f : jclass.fields().values()) {
            if (f.type().isArray()) {
                method.body().invoke(dest, "writeList").arg(f);
            } else {
                method.body().invoke(dest, "writeValue").arg(f);
            }
        }
    }
    
    public void addDescribeContents(JDefinedClass jclass) {
        JMethod method = jclass.method(JMod.PUBLIC, int.class, "describeContents");
        method.body()._return(JExpr.lit(0));
    }
    
    public void addCreator(JDefinedClass jclass) {
        JClass creatorType = jclass.owner().ref(Creator.class).narrow(jclass); 
        JDefinedClass creatorClass = jclass.owner().anonymousClass(creatorType);
        
        addCreateFromParcel(jclass, creatorClass);
        addNewArray(jclass, creatorClass);
        
        JFieldVar creatorField = jclass.field(JMod.PUBLIC | JMod.STATIC | JMod.FINAL, creatorType, "CREATOR");
        creatorField.init(JExpr._new(creatorClass));
    }

    private void addNewArray(JDefinedClass jclass, JDefinedClass creatorClass) {
        JMethod newArray = creatorClass.method(JMod.PUBLIC, jclass.array(), "newArray");
        newArray.param(int.class, "size");
        newArray.body()._return(JExpr.direct("new " + jclass.name() + "[size]"));
    }

    private void addCreateFromParcel(JDefinedClass jclass, JDefinedClass creatorClass) {
        JMethod createFromParcel = creatorClass.method(JMod.PUBLIC, jclass, "createFromParcel");
        JVar in = createFromParcel.param(Parcel.class, "in");
        JVar instance = createFromParcel.body().decl(jclass, "instance", JExpr._new(jclass));
        for (JFieldVar f : jclass.fields().values()) {
            if (f.type().isArray()) {
                createFromParcel.body()
                        .invoke(in, "readList")
                        .arg(instance.ref(f))
                        .arg(JExpr.direct(f.type().erasure().name() + ".class.getClassLoader()"));
             } else {
                createFromParcel.body().assign(
                        instance.ref(f),
                        JExpr.cast(
                                f.type(),
                                in.invoke("readValue").arg(JExpr.direct(f.type().erasure().name() + ".class.getClassLoader()"))
                        )
                );
            }

        }
        createFromParcel.body()._return(instance);
    }
    
}

@@ -691,17 +691,16 @@
 reator;%0A
-%0A
 import c
@@ -720,219 +720,11 @@
 del.
-JClass;%0Aimport com.sun.codemodel.JDefinedClass;%0Aimport com.sun.codemodel.JExpr;%0Aimport com.sun.codemodel.JFieldVar;%0Aimport com.sun.codemodel.JMethod;%0Aimport com.sun.codemodel.JMod;%0Aimport com.sun.codemodel.JVar;
+*;%0A
 %0A%0Apu
@@ -1076,32 +1076,54 @@
 f (f.type().
-isArray(
+erasure().name().equals(%22List%22
 )) %7B%0A       
@@ -2723,16 +2723,38 @@
 e().
-isArray(
+erasure().name().equals(%22List%22
 )) %7B
@@ -2934,32 +2934,31 @@
 ect(
-f.type().erasure().name(
+getGenericType(f.type()
 ) + 
@@ -3430,15 +3430,713 @@
 ;%0A    %7D%0A
+%0A
     
+private String getGenericType(JType jType) %7B%0A        if (jType.erasure().name().equals(%22List%22)) %7B%0A            final String typeName = jType.fullName();%0A            int start = 0;%0A            int end = typeName.length();%0A%0A            for (int i = 0; i %3C typeName.length(); ++i) %7B%0A                switch (typeName.charAt(i)) %7B%0A                    case '%3C':%0A                        start = i;%0A                        break;%0A                    case '%3E':%0A                        end = i;%0A                        break;%0A                %7D%0A            %7D%0A            // plus one for excluding '%3C'%0A            return typeName.substring(start+1, end);%0A        %7D%0A        return jType.erasure().name();%0A    %7D%0A
 %0A%7D%0A

fix use the wrong class loader in unmarshal parcelable