BUG: Various inconsistencies in DataFrame getitem/setitem behavior (fixes #2765)

fixes #2765 

Note, to address ` __getitem__` does not reindex boolean Series key but `__setitem__` does ", I have changed the `__getitem__` behavior rather than the `__setitem__` behavior because it is more consistent with other indexing behavior and does not break any tests...just in case, I have inserted a warning about this happening (which only triggers when a reindex is actually required)

Also, in addition to resolving the bugs, I have refactored the code to make `__getitem__` and `__setitem__` code paths as symmetric as possible, in order to help prevent more issues in the future.

Unit test coverage added, and performance tests show no impact