
/*
 * 
 *   Copyright 2016 RIFT.IO Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
var React = require('react');
var mixin = require('../mixins/ButtonEventListener.js')
//TODO: Many values are hard coded, need to make bullet "smarter"
/**
 *  A bullet graph component.
 *  It's props values and a brief description below
 *
 *  vertical: If true, the bar rises and falls vertically
 *  value:    The value displayed
 *  min:      The minimum value expected
 *  max:      The maximum value expected
 *  bulletColor: The fill color of the value section of the graph
 *  radius:   Radius of graph corners.
 *  containerMarginX: Container's margin along x-axis
 *  containerMarginY: Container's margin along y-axis
 *  width:    Width of bullet graph in pixels
 *  height:   Height of bullet graph in pixels
 *  fontSize:  Font size of text in pixels
 *  textMarginX: margin for text on x-axis
 *  textMarginY: Margin for text on y-axis
 *  units:    units displayed. Also changes whether a max value is displayed.
 **/
module.exports = React.createClass({
  displayName: 'Bullet',
  mixins:mixin.MIXINS,
  propTypes: {
    vertical: React.PropTypes.bool,
    value: React.PropTypes.number,
    min: React.PropTypes.number,
    max: React.PropTypes.number,
    bulletColor: React.PropTypes.string,
    radius: React.PropTypes.number,
    containerMarginX: React.PropTypes.number,
    containerMarginY: React.PropTypes.number,
    bulletMargin: React.PropTypes.number,
    width: React.PropTypes.number,
    height: React.PropTypes.number,
    markerX: React.PropTypes.number,
    fontSize: React.PropTypes.number,
    textMarginX: React.PropTypes.number,
    textMarginY: React.PropTypes.number,
    units: React.PropTypes.string
  },

  getDefaultProps: function() {
    return {
        vertical: false,
        value: 0,
        min: 0,
        max: 100,
        bulletColor: "blue",
        radius: 4,
        containerMarginX: 0,
        containerMarginY: 0,
        bulletMargin: 0,
        width: 512,
        height: 64,
        markerX: -100,
        fontSize: 16,
        textMarginX: 5,
        textMarginY: 42,
        units:''
    }
  },

  /**
   * Defines default state.
   * value: The value displayed
   */
  getInitialState: function() {
    return {
        value: this.props.value
    }
  },

  /**
   * Called when the props are updated.
   * Syncs the state value with the prop value.
   * @params nextProps
   */
  componentWillReceiveProps: function(nextProps) {
    this.setState({value:nextProps.value || this.state.value})
  },

  /**
   * Before the component will mount, the width value is recalculed based on browser.
   */
  componentWillMount: function() {
        var isIE = false || !!document.documentMode;
        var range = this.props.max - this.props.min;
        var normalizedValue = (this.state.value - this.props.min) / range;
        this.isPercent = (!this.props.units || this.props.units == '')? true:false
        if (isIE) {
            this.bulletWidth = String(Math.round(100 * normalizedValue)) + "%";
        } else {
            this.bulletWidth = this.props.width - (2 * this.props.containerMarginX);
        }
        this.displayValue = (this.isPercent)? String(Math.round(normalizedValue * 100)) + "%" : this.props.value

  },

  /**
   * When the component mounts, this function sets the animation for smooth transition on value change.  This only
   * happens if the user's browser is not IE.
   */
  componentDidMount: function() {
        var isIE = false || !!document.documentMode;
        var range = this.props.max - this.props.min;
        var normalizedValue = (this.state.value - this.props.min) / range;
        if (!isIE) {
            var transform = "scaleX(" + normalizedValue + ")";
            var bullet = React.findDOMNode(this.refs.bulletRef);
            bullet.style.transform = transform;
            bullet.style["-webkit-transform"] = transform;
        }
  },

  /**
   * On update, reaplies transformation and width changes made in componentWillMount and componentDidMount
   * @param nextProps
   * @param nextState
   * @returns {boolean}
   */
  shouldComponentUpdate: function(nextProps, nextState) {

    if (String(this.state.value) == String(nextState.value)) {
      return false;
    } else {
        var isIE = false || !!document.documentMode;
        var range = this.props.max - this.props.min;
        var normalizedValue = (nextState.value - this.props.min) / range;

        if (isIE) {
            this.bulletWidth = String(Math.round(100 * normalizedValue)) + "%";
        } else {
            this.bulletWidth = this.props.width - (2 * this.props.containerMarginX);
            var transform = "scaleX(" + normalizedValue + ")";
            var bullet = React.findDOMNode(this.refs.bulletRef);
            bullet.style.transform = transform;
            bullet.style["-webkit-transform"] = transform;
        }
        this.displayValue = (this.isPercent)? String(Math.round(normalizedValue * 100)) + "%" : nextState.value

        return true;
    }
  },



  /**
   * Renders the Bullet Component
   * @returns {*}
   */
  render: function() {

    // The text element that displays the difference between the max value and the current value.
    var maxDOMEl = (!this.isPercent)? null : React.createElement("text", {
                //X needs better logic
                // x: this.props.width - this.props.height * 1.25,
                x: this.props.width - (130 - this.props.textMarginX),
                y: this.props.textMarginY,
                fontFamily: "Verdana",
                fontSize: this.props.fontSize,
                fill: "#ffffff"}, String(this.props.max - this.state.value) + "%");


        // The main bullet element.  Made up of a static black rect in the background,
        // a moving colored rect overlayed on top and a text element for the current value.
        var bulletDOM = React.createElement("svg", {
            width: "100%",
            height: "100%",
            viewBox: "0 0 512 " + this.props.height,
            preserveAspectRatio: "none"},
          React.createElement("rect", {className: "bullet-container",
                width: this.props.width - (2 * this.props.containerMarginX),
                height: this.props.height - (2 * this.props.containerMarginY),
                x: this.props.containerMarginX,
                y: this.props.containerMarginY,
                rx: this.props.radius,
                ry: this.props.radius}, null),
          React.createElement("svg", {
              x: this.props.containerMarginX,
              y: this.props.bulletMargin},
            React.createElement("rect", {
                className: "bullet",
                ref:"bulletRef",
                fill: this.props.bulletColor,
                width: this.bulletWidth,
                height: this.props.height - (2 * this.props.bulletMargin),
                rx: this.props.radius,
                ry: this.props.radius
            })
          ),
          React.createElement("line", {className: "bullet-marker",
                x1: this.props.markerX,
                x2: this.props.markerX,
                y1: this.props.markerY1,
                y2: this.props.markerY2}),
            React.createElement("text", {
                x: this.props.textMarginX,
                y: this.props.textMarginY,
                "fontFamily": "Verdana",
              "fontSize": this.props.fontSize,
              fill: "#ffffff"}, this.displayValue
              ),
            maxDOMEl
        );


    return bulletDOM;
  }
});
