/**注解：源程序中的一种标记，被用来在编译、测试、运行时做一些特殊的处理
 * 1.定义注解:annotation class xxx(para:Type)
 * 2.使用注解:@xxx(value)或@yyy:xxx(value)修饰类、函数、属性、getter/setter、构造器、参数等
 * 3.解析注解：用反射获取注解信息，然后做相应处理
 */
import java.awt.event.*
import kotlin.reflect.*
import javax.swing.*
import kotlin.reflect.full.*

fun main() {
    AnnotationTest().init()
}

//定义注解
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
    AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION,
    AnnotationTarget.CONSTRUCTOR,AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
@MustBeDocumented
annotation class Fancy

annotation class Special(val why: String="default value")


//使用注解
@Fancy class Foo1 {   //class
    @Fancy fun baz(@Fancy foo: Int): Int {     //function&Parameter
        return (@Fancy 1)     //return value
    }
}
class Foo3 @Fancy constructor(dependency: String) {   }    //constructor
class Foo4 {
    var x: String? = null
        @Fancy set
}  //setter
@Special("example") class Foo2 {}        //带参数的注解

val f = @Fancy { Thread.sleep(10) }    //Lambda表达式

class Foo5{
    @set:[Fancy Special]     //多个注解修饰同一个目标
    var name: String="Hello"
}

//注解属性值
annotation class ReplaceWith(val expression: String)
annotation class Deprecated(
    val message: String,
    val replaceWith: ReplaceWith = ReplaceWith(""))    //使用另一个注解作为参数
@Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
fun deprFun(){}

annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any>)  //使用类作为参数
@Ann(String::class, Int::class) class MyClass

//解析注解
// 指定该注解只能修饰属性
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
// 定义一个属性，用于设置元数据
// 该listener属性用于保存监听器实现类
annotation class ActionListenerFor(val listener: KClass<out ActionListener>)

// 处理注解的方法，其中obj是包含注解的对象
fun processAnnotations(obj: Any){
    // 获取obj对象的类
    val cl = obj::class
    // 获取指定obj对象的所有成员，并遍历每个成员
    for (prop in cl.memberProperties){
        // 获取该成员上ActionListenerFor类型的注解
        val a = prop.findAnnotation<ActionListenerFor>()
        // 获取属性prop的值
        val fObj = prop.call(obj)
        // 如果fObj是AbstractButton的实例，且a不为null
        if (a != null && fObj != null
            && fObj is AbstractButton){
            // 获取a注解里的listener属性值（它是一个监听器类）
            val listenerClazz = a.listener
            // 使用反射来创建listener类的对象
            val al = listenerClazz.createInstance()
            // 为fObj按钮添加事件监听器
            fObj.addActionListener(al)
        }
    }
}
class AnnotationTest{
    val mainWin = JFrame("使用注解绑定事件监听器")
    // 使用注解为ok按钮绑定事件监听器
    @ActionListenerFor(listener=OkListener::class)
    val ok = JButton("确定")
    // 使用注解为cancel按钮绑定事件监听器
    @ActionListenerFor(listener=CancelListener::class)
    val cancel = JButton("取消")
    fun init(){
        // 初始化界面的方法
        val jp = JPanel()
        jp.add(ok)
        jp.add(cancel)
        mainWin.add(jp)
        processAnnotations(this)      //调用注解处理方法
        mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        mainWin.pack()
        mainWin.setVisible(true)
    }
}
// 定义ok按钮的事件监听器实现类
class OkListener: ActionListener{
    override fun actionPerformed(evt: ActionEvent){
        JOptionPane.showMessageDialog(null, "单击了确认按钮")
    }
}
// 定义cancel按钮的事件监听器实现类
class CancelListener: ActionListener{
    override fun actionPerformed(evt: ActionEvent){
        JOptionPane.showMessageDialog(null, "单击了取消按钮")
    }
}