rewrote to a more extendable approach