Much refactoring, will be rebased.