Big refactoring. May be wrong.