/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Stephane Micheloud
 */


package scala.tools.nsc
package backend.jvm

import ch.epfl.lamp.fjbg._
import symtab.Flags

trait GenAndroid {
  self: GenJVM =>

  import global._
  import icodes._
  import opcodes._

  /** From the reference documentation of the Android SDK:
   *  The `Parcelable` interface identifies classes whose instances can be
   *  written to and restored from a `Parcel`. Classes implementing the
   *  `Parcelable` interface must also have a static field called `CREATOR`,
   *  which is an object implementing the `Parcelable.Creator` interface.
   */
  private val fieldName = newTermName("CREATOR")

  private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable")
  private lazy val AndroidCreatorClass        = rootMirror.getClassIfDefined("android.os.Parcelable$Creator")

  def isAndroidParcelableClass(sym: Symbol) =
    (AndroidParcelableInterface != NoSymbol) &&
    (sym.parentSymbols contains AndroidParcelableInterface)

  def addCreatorCode(codegen: BytecodeGenerator, block: BasicBlock) {
    import codegen._
    val fieldSymbol = (
      clasz.symbol.newValue(newTermName(fieldName), NoPosition, Flags.STATIC | Flags.FINAL)
        setInfo AndroidCreatorClass.tpe
    )
    val methodSymbol = definitions.getMember(clasz.symbol.companionModule, fieldName)
    clasz addField new IField(fieldSymbol)
    block emit CALL_METHOD(methodSymbol, Static(false))
    block emit STORE_FIELD(fieldSymbol, true)
  }

  def legacyAddCreatorCode(codegen: BytecodeGenerator, clinit: JExtendedCode) {
    import codegen._
    val creatorType = javaType(AndroidCreatorClass)
    jclass.addNewField(PublicStaticFinal,
                       fieldName,
                       creatorType)
    val moduleName = javaName(clasz.symbol)+"$"
    clinit.emitGETSTATIC(moduleName,
                         nme.MODULE_INSTANCE_FIELD.toString,
                         new JObjectType(moduleName))
    clinit.emitINVOKEVIRTUAL(moduleName, fieldName,
                             new JMethodType(creatorType, Array()))
    clinit.emitPUTSTATIC(jclass.getName(), fieldName, creatorType)
  }

}
