var React = require('react');
var Router = require('react-router');
var { Route, RouteHandler, Link } = Router;

class App extends React.Component {
  constructor () {
    this.state = {
      loggedIn: auth.loggedIn()
    };
  }

  setStateOnAuth (loggedIn) {
    this.setState({
      loggedIn: loggedIn
    });
  }

  componentWillMount () {
    auth.onChange = this.setStateOnAuth.bind(this);
    auth.login();
  }

  render () {
    return (
      <div>
        <ul>
          <li>
            {this.state.loggedIn ? (
              <Link to="logout">Log out</Link>
            ) : (
              <Link to="login">Sign in</Link>
            )}
          </li>
          <li><Link to="about">About</Link></li>
          <li><Link to="dashboard">Dashboard</Link> (authenticated)</li>
        </ul>
        <RouteHandler/>
      </div>
    );
  }
}

var requireAuth = (Component) => {
  class Authenticated extends React.Component {
    render () {
      return <Component {...this.props}/>
    }
  }

  Authenticated.willTransitionTo = function (transition) {
    var nextPath = transition.path;
    if (!auth.loggedIn()) {
      transition.redirect('/login',{},
        { 'nextPath' : nextPath });
    }
  };

  return Authenticated;
};

var Dashboard = requireAuth(class extends React.Component {
  render () {
    var token = auth.getToken();
    return (
      <div>
        <h1>Dashboard</h1>
        <p>You made it!</p>
        <p>{token}</p>
      </div>
    );
  }
});

class Login extends React.Component {

  constructor () {
    this.handleSubmit = this.handleSubmit.bind(this);
    this.state = {
      error: false
    };
  }

  handleSubmit (event) {
    event.preventDefault();
    var { router } = this.context;
    var nextPath = router.getCurrentQuery().nextPath;
    var email = this.refs.email.getDOMNode().value;
    var pass = this.refs.pass.getDOMNode().value;
    auth.login(email, pass, (loggedIn) => {
      if (!loggedIn)
        return this.setState({ error: true });
      if (nextPath) {
        router.replaceWith(nextPath);
      } else {
        router.replaceWith('/about');
      }
    });
  }

  render () {
    return (
      <form onSubmit={this.handleSubmit}>
        <label><input ref="email" placeholder="email" defaultValue="joe@example.com"/></label>
        <label><input ref="pass" placeholder="password"/></label> (hint: password1)<br/>
        <button type="submit">login</button>
        {this.state.error && (
          <p>Bad login information</p>
        )}
      </form>
    );
  }
}

Login.contextTypes = {
  router: React.PropTypes.func
};

class About extends React.Component {
  render () {
    return <h1>About</h1>;
  }
}

class Logout extends React.Component {
  componentDidMount () {
    auth.logout();
  }

  render () {
    return <p>You are now logged out</p>;
  }
}


// Fake authentication lib

var auth = {
  login (email, pass, cb) {
    cb = arguments[arguments.length - 1];
    if (localStorage.token) {
      if (cb) cb(true);
      this.onChange(true);
      return;
    }
    pretendRequest(email, pass, (res) => {
      if (res.authenticated) {
        localStorage.token = res.token;
        if (cb) cb(true);
        this.onChange(true);
      } else {
        if (cb) cb(false);
        this.onChange(false);
      }
    });
  },

  getToken: function () {
    return localStorage.token;
  },

  logout: function (cb) {
    delete localStorage.token;
    if (cb) cb();
    this.onChange(false);
  },

  loggedIn: function () {
    return !!localStorage.token;
  },

  onChange: function () {}
};

function pretendRequest(email, pass, cb) {
  setTimeout(() => {
    if (email === 'joe@example.com' && pass === 'password1') {
      cb({
        authenticated: true,
        token: Math.random().toString(36).substring(7)
      });
    } else {
      cb({authenticated: false});
    }
  }, 0);
}

var routes = (
  <Route handler={App}>
    <Route name="login" handler={Login}/>
    <Route name="logout" handler={Logout}/>
    <Route name="about" handler={About}/>
    <Route name="dashboard" handler={Dashboard}/>
  </Route>
);

Router.run(routes, function (Handler) {
  React.render(<Handler/>, document.getElementById('example'));
});

@@ -883,16 +883,23 @@
  =%3E %7B%0A  
+return 
 class Au
@@ -944,89 +944,15 @@
     
-render () %7B%0A      return %3CComponent %7B...this.props%7D/%3E%0A    %7D%0A  %7D%0A%0A  Authenticated.
+static 
 will
@@ -967,20 +967,8 @@
 onTo
- = function 
 (tra
@@ -984,42 +984,8 @@
 %7B%0A  
-  var nextPath = transition.path;%0A
     
@@ -1004,24 +1004,26 @@
 ggedIn()) %7B%0A
+  
       transi
@@ -1049,22 +1049,14 @@
 in',
+ 
 %7B%7D,
-%0A       
  %7B
- 
 'nex
@@ -1068,25 +1068,31 @@
 ' : 
-nextP
+transition.p
 ath
- 
 %7D);%0A    
 %7D%0A  
@@ -1091,39 +1091,87 @@
     
-%7D%0A  %7D;%0A%0A  return Authenticated;
+  %7D  %0A    %7D%0A    render () %7B%0A      return %3CComponent %7B...this.props%7D/%3E%0A    %7D%0A  %7D
 %0A%7D;%0A

Make requireAuth more ES6ish.