/* 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/. */

"use strict";

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

const Constants = require("../constants");
const Types = require("../types");

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

  propTypes: {
    viewport: PropTypes.shape(Types.viewport).isRequired,
    onRemoveDevice: PropTypes.func.isRequired,
    onResizeViewport: PropTypes.func.isRequired,
  },

  getInitialState() {
    let { width, height } = this.props.viewport;

    return {
      width,
      height,
      isEditing: false,
      isInvalid: false,
    };
  },

  componentWillReceiveProps(nextProps) {
    let { width, height } = nextProps.viewport;

    this.setState({
      width,
      height,
    });
  },

  validateInput(value) {
    let isInvalid = true;

    // Check the value is a number and greater than MIN_VIEWPORT_DIMENSION
    if (/^\d{3,4}$/.test(value) &&
        parseInt(value, 10) >= Constants.MIN_VIEWPORT_DIMENSION) {
      isInvalid = false;
    }

    this.setState({
      isInvalid,
    });
  },

  onInputBlur() {
    let { width, height } = this.props.viewport;

    if (this.state.width != width || this.state.height != height) {
      this.onInputSubmit();
    }

    this.setState({
      isEditing: false,
      inInvalid: false,
    });
  },

  onInputChange({ target }) {
    if (target.value.length > 4) {
      return;
    }

    if (this.refs.widthInput == target) {
      this.setState({ width: target.value });
      this.validateInput(target.value);
    }

    if (this.refs.heightInput == target) {
      this.setState({ height: target.value });
      this.validateInput(target.value);
    }
  },

  onInputFocus() {
    this.setState({
      isEditing: true,
    });
  },

  onInputKeyUp({ target, keyCode }) {
    // On Enter, submit the input
    if (keyCode == 13) {
      this.onInputSubmit();
    }

    // On Esc, blur the target
    if (keyCode == 27) {
      target.blur();
    }
  },

  onInputSubmit() {
    if (this.state.isInvalid) {
      let { width, height } = this.props.viewport;

      this.setState({
        width,
        height,
        isInvalid: false,
      });

      return;
    }

    // Change the device selector back to an unselected device
    // TODO: Bug 1332754: Logic like this probably belongs in the action creator.
    if (this.props.viewport.device) {
      this.props.onRemoveDevice();
    }
    this.props.onResizeViewport(parseInt(this.state.width, 10),
                                parseInt(this.state.height, 10));
  },

  render() {
    let editableClass = "viewport-dimension-editable";
    let inputClass = "viewport-dimension-input";

    if (this.state.isEditing) {
      editableClass += " editing";
      inputClass += " editing";
    }

    if (this.state.isInvalid) {
      editableClass += " invalid";
    }

    return dom.div(
      {
        className: "viewport-dimension",
      },
      dom.div(
        {
          className: editableClass,
        },
        dom.input({
          ref: "widthInput",
          className: inputClass,
          size: 4,
          value: this.state.width,
          onBlur: this.onInputBlur,
          onChange: this.onInputChange,
          onFocus: this.onInputFocus,
          onKeyUp: this.onInputKeyUp,
        }),
        dom.span({
          className: "viewport-dimension-separator",
        }, "×"),
        dom.input({
          ref: "heightInput",
          className: inputClass,
          size: 4,
          value: this.state.height,
          onBlur: this.onInputBlur,
          onChange: this.onInputChange,
          onFocus: this.onInputFocus,
          onKeyUp: this.onInputKeyUp,
        })
      )
    );
  },

});
