Final Version! (only a few comments are missing)