reimplementation fixing several bugs and adding functionality