Refactor to templates

- refactor using templates
- add some more functional tests