Merged code, need some more work
many optimizations