/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

/* eslint-env browser */
"use strict";

// A box with a start and a end pane, separated by a dragable splitter that
// allows the user to resize the relative widths of the panes.
//
//     +-----------------------+---------------------+
//     |                       |                     |
//     |                       |                     |
//     |                       S                     |
//     |      Start Pane       p     End Pane        |
//     |                       l                     |
//     |                       i                     |
//     |                       t                     |
//     |                       t                     |
//     |                       e                     |
//     |                       r                     |
//     |                       |                     |
//     |                       |                     |
//     +-----------------------+---------------------+

const {
  DOM: dom,
  createClass,
  PropTypes,
} = require("devtools/client/shared/vendor/react");
const { assert } = require("devtools/shared/DevToolsUtils");

module.exports = createClass({
  displayName: "HSplitBox",

  propTypes: {
    // The contents of the start pane.
    start: PropTypes.any.isRequired,

    // The contents of the end pane.
    end: PropTypes.any.isRequired,

    // The relative width of the start pane, expressed as a number between 0 and
    // 1. The relative width of the end pane is 1 - startWidth. For example,
    // with startWidth = .5, both panes are of equal width; with startWidth =
    // .25, the start panel will take up 1/4 width and the end panel will take
    // up 3/4 width.
    startWidth: PropTypes.number,

    // A minimum css width value for the start and end panes.
    minStartWidth: PropTypes.any,
    minEndWidth: PropTypes.any,

    // A callback fired when the user drags the splitter to resize the relative
    // pane widths. The function is passed the startWidth value that would put
    // the splitter underneath the users mouse.
    onResize: PropTypes.func.isRequired,
  },

  getDefaultProps() {
    return {
      startWidth: 0.5,
      minStartWidth: "20px",
      minEndWidth: "20px",
    };
  },

  getInitialState() {
    return {
      mouseDown: false
    };
  },

  componentDidMount() {
    document.defaultView.top.addEventListener("mouseup", this._onMouseUp,
                                              false);
    document.defaultView.top.addEventListener("mousemove", this._onMouseMove,
                                              false);
  },

  componentWillUnmount() {
    document.defaultView.top.removeEventListener("mouseup", this._onMouseUp,
                                                 false);
    document.defaultView.top.removeEventListener("mousemove", this._onMouseMove,
                                                 false);
  },

  _onMouseDown(event) {
    if (event.button !== 0) {
      return;
    }

    this.setState({ mouseDown: true });
    event.preventDefault();
  },

  _onMouseUp(event) {
    if (event.button !== 0 || !this.state.mouseDown) {
      return;
    }

    this.setState({ mouseDown: false });
    event.preventDefault();
  },

  _onMouseMove(event) {
    if (!this.state.mouseDown) {
      return;
    }

    const rect = this.refs.box.getBoundingClientRect();
    const { left, right } = rect;
    const width = right - left;
    const relative = event.clientX - left;
    this.props.onResize(relative / width);

    event.preventDefault();
  },

  render() {
    /* eslint-disable no-shadow */
    const { start, end, startWidth, minStartWidth, minEndWidth } = this.props;
    assert(startWidth => 0 && startWidth <= 1,
           "0 <= this.props.startWidth <= 1");
    /* eslint-enable */
    return dom.div(
      {
        className: "h-split-box",
        ref: "box",
      },

      dom.div(
        {
          className: "h-split-box-pane",
          style: { flex: startWidth, minWidth: minStartWidth },
        },
        start
      ),

      dom.div({
        className: "devtools-side-splitter",
        onMouseDown: this._onMouseDown,
      }),

      dom.div(
        {
          className: "h-split-box-pane",
          style: { flex: 1 - startWidth, minWidth: minEndWidth },
        },
        end
      )
    );
  }
});