most bug fixed. TODO: refactory