{{>licenseInfo}}

package {{package}};

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.List;

import com.walmartlabs.electrode.reactnative.bridge.Bridgeable;

import static com.walmartlabs.electrode.reactnative.bridge.util.BridgeArguments.*;
{{#models}}
{{#model}}

{{#description}}
/**
 * {{description}}
 */
{{/description}}
public class {{classname}} implements Parcelable, Bridgeable {
{{#classname}}
    public static final Creator<{{classname}}> CREATOR =
            new Creator<{{classname}}>() {
                @Override
                public {{classname}} createFromParcel(Parcel in) {
                    return new {{classname}}(in);
                }

                @Override
                public {{classname}}[] newArray(int size) {
                    return new {{classname}}[size];
                }
            };

{{/classname}}
{{#vars}}
    private {{{datatype}}} {{name}};
{{/vars}}

    private {{classname}}() {
    }

    private {{classname}}(Builder builder) {
{{#vars}}
        this.{{name}} = builder.{{name}};
{{/vars}}
    }

    private {{classname}}(Parcel in) {
        this(in.readBundle());
    }

    public {{classname}}(@NonNull Bundle bundle) {
{{#requiredVars}}
        if (!bundle.containsKey("{{name}}")) {
            throw new IllegalArgumentException("{{name}} property is required");
        }

{{/requiredVars}}
{{#allVars}}
{{#isListContainer}}
{{#items}}
{{#isString}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getStringArray("{{baseName}}"), String.class) : null;
{{/isString}}
{{#isInteger}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getIntArray("{{baseName}}"), Integer.class) : null;
{{/isInteger}}
{{#isBoolean}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getBooleanArray("{{baseName}}"), Boolean.class) : null;
{{/isBoolean}}
{{#isLong}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getLongArray("{{baseName}}"), Long.class) : null;
{{/isLong}}
{{#isDouble}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getDoubleArray("{{baseName}}"), Double.class) : null;
{{/isDouble}}
{{#isFloat}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getFloatArray("{{baseName}}"), Float.class) : null;
{{/isFloat}}
{{^isPrimitiveType}}
        this.{{baseName}} = bundle.containsKey("{{baseName}}") ? getList(bundle.getParcelableArray("{{baseName}}"), {{{datatype}}}.class) : null;
{{/isPrimitiveType}}
{{/items}}
{{/isListContainer}}
{{^isListContainer}}
{{#isString}}
        this.{{name}} = bundle.getString("{{name}}");
{{/isString}}
{{#isInteger}}
        this.{{name}} = getNumberValue(bundle, "{{name}}") == null ? null : getNumberValue(bundle, "{{name}}").intValue();
{{/isInteger}}
{{#isBoolean}}
        this.{{name}} = bundle.containsKey("{{name}}") ? bundle.getBoolean("{{name}}") : null;
{{/isBoolean}}
{{#isLong}}
        this.{{name}} = getNumberValue(bundle, "{{name}}") == null ? null : getNumberValue(bundle, "{{name}}").longValue();
{{/isLong}}
{{#isDouble}}
        this.{{name}} = bundle.getDouble("{{name}}");
{{/isDouble}}
{{#isFloat}}
        this.{{name}} = getNumberValue(bundle, "{{name}}") == null ? null : getNumberValue(bundle, "{{name}}").floatValue();
{{/isFloat}}
{{#isObject}}
        this.{{name}} = bundle.containsKey("{{name}}") ? bundle.getBundle("{{name}}") : null;
{{/isObject}}
{{^isPrimitiveType}}
        this.{{name}} = bundle.containsKey("{{name}}") ? new {{{datatype}}}(bundle.getBundle("{{name}}")) : null;
{{/isPrimitiveType}}
{{/isListContainer}}
{{/allVars}}
    }
{{#vars}}

{{#description}}
    /**
     * {{description}}
     *
     * @return {{{datatype}}}
     */
{{/description}}
{{#required}}
    @NonNull
{{/required}}
{{^required}}
    @Nullable
{{/required}}
    public {{{datatype}}} {{getter}}() {
        return {{name}};
    }
{{/vars}}

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeBundle(toBundle());
    }

    @NonNull
    @Override
    public Bundle toBundle() {
        Bundle bundle = new Bundle();
{{#requiredVars}}
{{#isListContainer}}
        updateBundleWithList(this.{{name}}, bundle, "{{name}}");
{{/isListContainer}}
{{^isListContainer}}
{{#isString}}
        bundle.putString("{{name}}", this.{{name}});
{{/isString}}
{{#isInteger}}
        bundle.putInt("{{name}}", this.{{name}});
{{/isInteger}}
{{#isLong}}
        bundle.putLong("{{name}}", this.{{name}});
{{/isLong}}
{{#isDouble}}
        bundle.putDouble("{{name}}", this.{{name}});
{{/isDouble}}
{{#isFloat}}
        bundle.putFloat("{{name}}", this.{{name}});
{{/isFloat}}
{{#isBoolean}}
        bundle.putBoolean("{{name}}", this.{{name}});
{{/isBoolean}}
{{^isPrimitiveType}}
        bundle.putBundle("{{name}}", this.{{name}}.toBundle());
{{/isPrimitiveType}}
{{/isListContainer}}
{{/requiredVars}}
{{#optionalVars}}
{{#isListContainer}}
        if (this.{{name}} != null) {
            updateBundleWithList(this.{{name}}, bundle, "{{name}}");
        }
{{/isListContainer}}
{{^isListContainer}}
{{#isString}}
        if ({{name}} != null) {
            bundle.putString("{{name}}", this.{{name}});
        }
{{/isString}}
{{#isInteger}}
        if (this.{{name}} != null) {
            bundle.putInt("{{name}}", this.{{name}});
        }
{{/isInteger}}
{{#isLong}}
        if (this.{{name}} != null) {
            bundle.putLong("{{name}}", this.{{name}});
        }
{{/isLong}}
{{#isDouble}}
        if (this.{{name}} != null) {
            bundle.putDouble("{{name}}", this.{{name}});
         }
{{/isDouble}}
{{#isFloat}}
        if (this.{{name}} != null) {
           bundle.putFloat("{{name}}", this.{{name}});
        }
{{/isFloat}}
{{#isBoolean}}
        if (this.{{name}} != null) {
            bundle.putBoolean("{{name}}", this.{{name}});
        }
{{/isBoolean}}
{{^isPrimitiveType}}
        if (this.{{name}} != null) {
            bundle.putBundle("{{name}}", this.{{name}}.toBundle());
        }
{{/isPrimitiveType}}
{{/isListContainer}}
{{/optionalVars}}
        return bundle;
    }

    @Override
    public String toString() {
        return "{"
{{#allVars}}
{{#isListContainer}}
                + "{{name}}:" + ({{name}} != null ? {{name}}.toString() : null){{^-last}} + ","{{/-last}}
{{/isListContainer}}
{{#isString}}
                + "{{name}}:" + ({{name}} != null ? "\"" + {{name}} + "\"" : null){{^-last}} + ","{{/-last}}
{{/isString}}
{{^isListContainer}}
{{^isString}}
{{#isPrimitiveType}}
                + "{{name}}:" + {{name}}{{^-last}} + ","{{/-last}}
{{/isPrimitiveType}}
{{/isString}}
{{^isPrimitiveType}}
                + "{{name}}:" + ({{name}} != null ? {{name}}.toString() : null){{^-last}} + ","{{/-last}}
{{/isPrimitiveType}}
{{/isListContainer}}
{{/allVars}}
                + "}";
    }

    public static class Builder {
{{#requiredVars}}
        private final {{{datatype}}} {{name}};
{{/requiredVars}}
{{#optionalVars}}
        private {{{datatype}}} {{name}};
{{/optionalVars}}

        public Builder({{#requiredVars}}@NonNull {{{datatype}}} {{name}}{{^-last}}, {{/-last}}{{/requiredVars}}) {
{{#requiredVars}}
            this.{{name}} = {{name}};
{{/requiredVars}}
        }
{{#optionalVars}}

        @NonNull
        public Builder {{name}}(@Nullable {{{datatype}}} {{name}}) {
            this.{{name}} = {{name}};
            return this;
        }
{{/optionalVars}}

        @NonNull
        public {{classname}} build() {
            return new {{classname}}(this);
        }
    }
}
{{/model}}
{{/models}}
