import {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';

import {
  updateSparkStatus,
  registerDevice,
  storeSparkInstance
} from './actions';

import createSpark from './spark';

const metricName = {
  SPARK_AUTHENTICATED: {
    resource: `spark`,
    event: `authentication`,
    action: `authenticated`
  },
  DEVICE_REGISTERED: {
    resource: `device`,
    event: `registration`,
    action: `registered`
  }
};

class SparkComponent extends Component {

  componentDidMount() {
    const {
      accessToken,
      metrics
    } = this.props;

    const props = this.props;
    let spark = props.spark.get(`spark`);

    if (!spark) {
      spark = createSpark(accessToken);
      props.storeSparkInstance(spark);
    }

    spark.listenToAndRun(spark, `change:canAuthorize`, () => {
      if (metrics && spark.canAuthorize) {
        metrics.sendElapsedTime(metricName.SPARK_AUTHENTICATED, spark);
      }
      props.updateSparkStatus({authenticated: spark.canAuthorize});
    });

    spark.listenToAndRun(spark, `change:isAuthenticating`, () => {
      props.updateSparkStatus({authenticating: spark.isAuthenticating});
    });

    spark.listenToAndRun(spark.device, `change:registered`, () => {
      if (metrics && spark.device.registered) {
        metrics.sendElapsedTime(metricName.DEVICE_REGISTERED, spark);
      }
      props.updateSparkStatus({registered: spark.device.registered});
    });

    this.setupDevice(spark, props);
  }

  componentWillReceiveProps(nextProps) {
    const spark = nextProps.spark.get(`spark`);
    this.setupDevice(spark, nextProps);
  }

  shouldComponentUpdate(nextProps) {
    const props = this.props;
    return nextProps.spark !== props.spark;
  }

  setupDevice(spark, props) {
    const {
      authenticated,
      registered,
      registering
    } = props.spark.get(`status`).toJS();

    if (authenticated && !registered && !registering) {
      props.registerDevice(spark);
    }
  }

  render() {
    return null;
  }
}

const injectedPropTypes = {
  registerDevice: PropTypes.func,
  spark: PropTypes.object
};

SparkComponent.propTypes = {
  accessToken: PropTypes.string.isRequired,
  ...injectedPropTypes
};

export default connect(
  (state) => ({
    mercury: state.mercury,
    spark: state.spark
  }),
  (dispatch) => bindActionCreators({
    updateSparkStatus,
    registerDevice,
    storeSparkInstance
  }, dispatch)
)(SparkComponent);

import {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';

import {
  updateSparkStatus,
  registerDevice,
  storeSparkInstance
} from './actions';

import createSpark from './spark';

const metricName = {
  SPARK_AUTHENTICATED: {
    resource: `spark`,
    event: `authentication`,
    action: `authenticated`
  },
  DEVICE_REGISTERED: {
    resource: `device`,
    event: `registration`,
    action: `registered`
  }
};

class SparkComponent extends Component {

  componentDidMount() {
    const {
      accessToken,
      metrics
    } = this.props;

    const props = this.props;
    let spark = props.spark.get(`spark`);

    if (!spark) {
      spark = createSpark(accessToken);
      props.storeSparkInstance(spark);
    }

    spark.listenToAndRun(spark, `change:canAuthorize`, () => {
      if (metrics && spark.canAuthorize) {
        metrics.sendElapsedTime(metricName.SPARK_AUTHENTICATED, spark);
      }
      props.updateSparkStatus({authenticated: spark.canAuthorize});
    });

    spark.listenToAndRun(spark, `change:isAuthenticating`, () => {
      props.updateSparkStatus({authenticating: spark.isAuthenticating});
    });

    spark.listenToAndRun(spark.device, `change:registered`, () => {
      if (metrics && spark.device.registered) {
        metrics.sendElapsedTime(metricName.DEVICE_REGISTERED, spark);
      }
      props.updateSparkStatus({registered: spark.device.registered});
    });

    this.setupDevice(spark, props);
  }

  componentWillReceiveProps(nextProps) {
    const spark = nextProps.spark.get(`spark`);
    this.setupDevice(spark, nextProps);
  }

  shouldComponentUpdate(nextProps) {
    const props = this.props;
    return nextProps.spark !== props.spark;
  }

  setupDevice(spark, props) {
    const {
      authenticated,
      registered,
      registerError,
      registering
    } = props.spark.get(`status`).toJS();

    if (authenticated && !registered && !registering && !registerError) {
      props.registerDevice(spark);
    }
  }

  render() {
    return null;
  }
}

const injectedPropTypes = {
  registerDevice: PropTypes.func,
  spark: PropTypes.object
};

SparkComponent.propTypes = {
  accessToken: PropTypes.string.isRequired,
  ...injectedPropTypes
};

export default connect(
  (state) => ({
    mercury: state.mercury,
    spark: state.spark
  }),
  (dispatch) => bindActionCreators({
    updateSparkStatus,
    registerDevice,
    storeSparkInstance
  }, dispatch)
)(SparkComponent);

stop attempting to register on failure