its too long to fit in a single comment... its about 600 lines of code!