not time to explain, take this (some cleanup and refactoring, might contain errors, because had not much time to test)