Refactored to OO - this has not been fully tested and may have broken stuff.