import React from 'react';
import ReactDOM from 'react-dom';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import { ContextMenuLayer as contextMenuLayer } from 'react-contextmenu';

import Immutable from 'immutable';

import CodeCell from './code-cell';
import MarkdownCell from './markdown-cell';
import Toolbar from './toolbar';

import {
  focusCell,
  focusPreviousCell,
  focusNextCell,
  copyCell,
  pasteCell,
} from '../../actions';

export class Cell extends React.Component {
  static propTypes = {
    cell: React.PropTypes.any,
    displayOrder: React.PropTypes.instanceOf(Immutable.List),
    cellStatus: React.PropTypes.instanceOf(Immutable.Map),
    id: React.PropTypes.string,
    getCompletions: React.PropTypes.func,
    focusedCell: React.PropTypes.string,
    language: React.PropTypes.string,
    onCellChange: React.PropTypes.func,
    running: React.PropTypes.bool,
    theme: React.PropTypes.string,
    pagers: React.PropTypes.instanceOf(Immutable.List),
    transforms: React.PropTypes.instanceOf(Immutable.Map),
  };

  static contextTypes = {
    store: React.PropTypes.object,
  };

  constructor() {
    super();
    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    this.selectCell = this.selectCell.bind(this);
    this.focusAboveCell = this.focusAboveCell.bind(this);
    this.focusBelowCell = this.focusBelowCell.bind(this);
    this.setCellHoverState = this.setCellHoverState.bind(this);
    this.setToolbarHoverState = this.setToolbarHoverState.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleKeyUp = this.handleKeyUp.bind(this);
    this.copyCell = this.copyCell.bind(this);
    this.pasteCell = this.pasteCell.bind(this);
  }

  state = {
    hoverCell: false,
    hoverToolbar: false,
    ctrlDown: false,
  };

  componentWillMount() {
    // Listen to the page level mouse move event and manually check for
    // intersection because we don't want the hover region to actually capture
    // any mouse events.  The hover region is an invisible element that
    // describes the "hot region" that toggles the creator buttons.
    document.addEventListener('mousemove', this.setCellHoverState, false);
  }

  componentWillUnmount() {
    document.removeEventListener('mousemove', this.setCellHoverState);
  }

  setCellHoverState(mouseEvent) {
    if (this.refs.cell) {
      const cell = ReactDOM.findDOMNode(this.refs.cell);
      if (cell) {
        const x = mouseEvent.clientX;
        const y = mouseEvent.clientY;
        const regionRect = cell.getBoundingClientRect();
        const hoverCell = (regionRect.left < x && x < regionRect.right) &&
                     (regionRect.top < y && y < regionRect.bottom);
        this.setState({ hoverCell });
      }
    }
  }

  setToolbarHoverState(hoverToolbar) {
    this.setState({ hoverToolbar });
  }

  handleKeyDown(event) {
    if (event.ctrlKey || event.keyCode === 91) {
      this.setState({ ctrlDown: true });
    }
  }

  handleKeyUp(event) {
    if (this.state.ctrlDown) {
      if (event.keyCode === 86) {
        this.setState({ ctrlDown: false });
        this.pasteCell();
      } else if (event.keyCode === 67) {
        this.setState({ ctrlDown: false });
        this.copyCell();
      }
    }
  }

  selectCell() {
    this.context.store.dispatch(focusCell(this.props.id));
  }

  focusAboveCell() {
    this.context.store.dispatch(focusPreviousCell(this.props.id));
  }

  focusBelowCell() {
    this.context.store.dispatch(focusNextCell(this.props.id));
  }

  copyCell() {
    this.context.store.dispatch(copyCell(this.props.id));
  }

  pasteCell() {
    this.context.store.dispatch(pasteCell());
  }

  render() {
    const cell = this.props.cell;
    const type = cell.get('cell_type');
    const focused = this.props.focusedCell === this.props.id;
    return (
      <div
        className={`cell ${type === 'markdown' ? 'text' : 'code'} ${focused ? 'focused' : ''}`}
        onClick={this.selectCell}
        onKeyDown={this.handleKeyDown}
        onKeyUp={this.handleKeyUp}
        ref="cell"
        onContextMenu={this.contextMenu}
      >
        {
          this.state.hoverCell || this.state.hoverToolbar ? <Toolbar
            type={type}
            setHoverState={this.setToolbarHoverState}
            cell={this.props.cell}
            id={this.props.id}
          /> : null
        }
        {
        type === 'markdown' ?
          <MarkdownCell
            focusAbove={this.focusAboveCell}
            focusBelow={this.focusBelowCell}
            focused={this.props.id === this.props.focusedCell}
            cell={this.props.cell}
            id={this.props.id}
            theme={this.props.theme}
          /> :
          <CodeCell
            focusAbove={this.focusAboveCell}
            focusBelow={this.focusBelowCell}
            focused={this.props.id === this.props.focusedCell}
            cell={this.props.cell}
            id={this.props.id}
            theme={this.props.theme}
            language={this.props.language}
            displayOrder={this.props.displayOrder}
            cellStatus={this.props.cellStatus}
            transforms={this.props.transforms}
            pagers={this.props.pagers}
            running={this.props.running}
            getCompletions={this.props.getCompletions}
          />
        }
      </div>
    );
  }
}

export default contextMenuLayer('cell-context-menu', (props) => ({
  id: props.id,
  type: props.cell.get('cell_type'),
}))(Cell);

@@ -405,33 +405,8 @@
 ll,%0A
-  copyCell,%0A  pasteCell,%0A
 %7D fr
@@ -1514,210 +1514,8 @@
 s);%0A
-    this.handleKeyDown = this.handleKeyDown.bind(this);%0A    this.handleKeyUp = this.handleKeyUp.bind(this);%0A    this.copyCell = this.copyCell.bind(this);%0A    this.pasteCell = this.pasteCell.bind(this);%0A
   %7D%0A
@@ -1578,29 +1578,8 @@
 se,%0A
-    ctrlDown: false,%0A
   %7D;
@@ -2632,421 +2632,8 @@
  %7D%0A%0A
-  handleKeyDown(event) %7B%0A    if (event.ctrlKey %7C%7C event.keyCode === 91) %7B%0A      this.setState(%7B ctrlDown: true %7D);%0A    %7D%0A  %7D%0A%0A  handleKeyUp(event) %7B%0A    if (this.state.ctrlDown) %7B%0A      if (event.keyCode === 86) %7B%0A        this.setState(%7B ctrlDown: false %7D);%0A        this.pasteCell();%0A      %7D else if (event.keyCode === 67) %7B%0A        this.setState(%7B ctrlDown: false %7D);%0A        this.copyCell();%0A      %7D%0A    %7D%0A  %7D%0A%0A
   se
@@ -2895,153 +2895,8 @@
  %7D%0A%0A
-  copyCell() %7B%0A    this.context.store.dispatch(copyCell(this.props.id));%0A  %7D%0A%0A  pasteCell() %7B%0A    this.context.store.dispatch(pasteCell());%0A  %7D%0A%0A
   re
@@ -3160,16 +3160,16 @@
 : ''%7D%60%7D%0A
+
         
@@ -3198,82 +3198,8 @@
 ll%7D%0A
-        onKeyDown=%7Bthis.handleKeyDown%7D%0A        onKeyUp=%7Bthis.handleKeyUp%7D%0A
     

Remove copy/paste logic from cell component