Add cache, do some refactoring