Completely rewrited and refactored.