## Session Service

The session service maintains and requests information about the authenticated
state of a user. A `session`, in the abstract, applies to the currently running
browser session. Thus it may, or may not, have a `currentUser`. It may
transition between states, but the session itself is a singleton.

Inject this service using Ember's DI APIs:

```js
import Component from 'ember-component';
import injectService from 'ember-service/inject';

export default Component.extend({
  session: injectService()
});
```

Over time, this service should replace much of the `Twitch.user` API
namespace. It already replaces calling `Twitch.user()` as a method call.
Additionally it should likely absorb much of the login controller.

### `Session service properties`

The session service supports initialization via `initializeSession`, and this
is performed in the application route when the app boots. Once that method
has been called, the service exposes a set of properties you can read
synchronously. For example:

```js
import Component from 'ember-component';
import injectService from 'ember-service/inject';

export default Component.extend({
  session: injectService(),
  click() {
    let { isAuthenticated, userData } = this.get('session');
    if (isAuthenticated) {
      doSomeLoggedInThing(userData.id);
    } else {
      userLoggedOut();
    }
  }
});
```

The available properties are:

* `isAuthenticated` - `true` when the user is logged in and `false` when they
  are logged out. `null` when authentication has not been performed, however
  in normal application usage after the application route has been entered
  the value is ensured to be `true` for `false`.
* `userData` - the user's non-mutable data. Only information that the user
  cannot edit in a running app (cannot change via settings) should be on this
  object. This is basically user data as returned from the `/me` API endpoint,
  however some mutable/configurable properties may be removed and instead be
  found on `userModel`. Again,
  `null` in the pre-application route state when authentication is unknown.
  If the user is not logged in this value will also be `null`, thus is should
  not be trusted to reflect authentication state. Please use `isAuthenticated`
  for tests of the user's authentication state.
* `userLogo` - a COMPUTED property that has the user's logo or a default placeholder
  if it is not present. Per API responses, the user logo is 300x300 and the
  placeholder is 150x150. NOTE: You MUST use get('userLogo') to access this value
* `userModel` - the user's mutable/configurable data. The user can edit this
  data while the app is running (for example displayName, logo). This is an
  ember-data record. Also `null` if the user is not authenticated and should
  not be trusted to represent `isAuthenticated` state.

### `withCurrentUser`

Trigger a callback when a user becomes authenticated, or if they are already
authenticated trigger the callback. `withCurrentUser` should be used
in cases where there is no logic for "when unauthenticated".

For example this click handler will alert the user's name, but if the
user is not logged in it will do nothing.

```js
import Component from 'ember-component';
import injectService from 'ember-service/inject';

export default Component.extend({
  session: injectService(),

  click() {
    let session = this.get('session');

    session.withCurrentUser(userData => {
      window.alert('hello ' + userData.name);
    });
  }
});
```

The promise resolves with `userData`, the same as `Twitch.user(fn)` is
called with.

### `getCurrentUser`

Fetch the current user, and return a promise that will resolve if they
are logged in and reject with a special object if they are logged out.

For example this click handler will alert the user's name, and if they
are logged out will alert a warning:

```js
import Component from 'ember-component';
import injectService from 'ember-service/inject';

export default Component.extend({
  session: injectService(),

  click() {
    let session = this.get('session');

    session.getCurrentUser().then(userData => {
      window.alert('hello ' + userData.name);
    }, error => {
      if (error && error.status === 401) {
        window.alert("You're not logged in at all!");
      } else {
        // If the error is not expected, then be sure to rethrow it
        throw error;
      }
    });
  }
});
```

The promise will resolve with `userData` just like `withCurrentUser`.
If the user is *not* logged in, then the promise will reject with the
following value:

```js
{ status: 401 }
```

You should test for this value to see if the error is simply a logged-out state,
or if there is an unexpected error that should be rethrown or handled. Unlike
with `withCurrentUser`, the developer using this API must handle unauthenticated
and error states.
