major refactor, instead of using lots of annotation, we should us @FunctionalInterface