<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
  <script src="SessionService.js"></script>
  <script src="app.js"></script>
  <title>spp.params</title>
</head>
<body ng-app="yourApp">
  <a href="?unicornId=magic&userId=stephen">Reload with some URL parameters</a>.

  <h3><code>Current URL</code></h3>
  <code>{{ location }}</code>

  <h3><code>localStorage.getItem('url-parameters');</code></h3>
  <code>{{ localStorageDump }}</code>
</body>
</html>
angular.module('yourApp', ['spp.params']).
  config(['SessionServiceProvider', function (SessionServiceProvider) {

    // You must define a key where the parameters will be saved into
    // localStorage.
    SessionServiceProvider.localStorageId = 'url-parameters';

    // SessionService allows you to customize the way warning messages are
    // displayed. Here, we just have a simple wrapper around the function that
    // will be called, `NotifierService`.
    SessionServiceProvider.NotifierService = function (message) {
      console.log('This is a custom warning message!', message);
    };

    // You must specify `parameters` as an array of object in the following
    // format...
    //
    // parameter {string}  The case-insensitive url parameter you want to cache.
    // required  {boolean} Should your application display a warning if this
    //                     parameter isn't specified?
    SessionServiceProvider.parameters = [
      {
        name: 'userId',
        required: true
      }, {
        name: 'unicornId',
        required: false
      }
    ];
  }]).
  run(['$rootScope', 'SessionService', '$window', function ($rootScope, SessionService, $window) {

    // You can choose when to run `SessionService.detect()`.
    //
    // Here, we're running it as soon as the application runs...
    SessionService.readParams();

    // ...as well as every time the route changes.
    $rootScope.$on('$routeChangeSuccess', SessionService.detect);

    $rootScope.localStorageDump = $window.localStorage.getItem('url-parameters');
    $rootScope.location = $window.location.search || 'Click the link above to load in some parameters.';;
  }]);
  
angular.module('spp.params', []).
  factory('SessionService',
  ['$location', '$window', '$log',
  function ($location, $window, $log) {
    'use strict';

    var NotifierService = this.NotifierService || $log.error;
    var expectedParameters = this.parameters;
    var localStorageId = this.localStorageId;

    if (!$window.localStorage) {
      return $log.debug('spp.params requires localStorage support.');
    }

    if (!expectedParameters) {
      return $log.debug('spp.params requires a list of properties.');
    }

    if (!localStorageId) {
      return $log.debug('spp.params requires a localStorage id.');
    }

    var properties = $window.localStorage.getItem(localStorageId);
    properties = properties ? JSON.parse(properties) : {};

    var keys = expectedParameters.map(function (property) {
      return property.name.toLowerCase();
    });

    var parameters = {};

    return {
      readParams: readParams,
      set: set,
      get: get
    };


    function buildParameterObject(params) {
      Object.keys(params).forEach(function (key) {
        parameters[key.toLowerCase()] = params[key];
      });
    }

    function readParameter(parameter) {
      var key = parameter.name.toLowerCase();
      var value = parameters[key];

      if (value) {
        set(key, value);
      }

      if (parameter.required && !properties[key]) {
        NotifierService(parameter.name + ' is required.',
          'Missing URL Parameter');
      }
    }

    function readParams() {
      buildParameterObject($location.search() || {});

      angular.forEach(expectedParameters, readParameter);
    }

    function get(property) {
      return properties[property.toLowerCase()];
    }

    function set(key, value) {
      var propertyKey = key.toLowerCase();

      if (keys.indexOf(propertyKey) === -1) {
        return $log.debug(key + ' was not an expected property.');
      }

      // Don't re-save the same value.
      if (properties[propertyKey] !== value) {
        $log.debug('Saving ' + propertyKey + ' to localStorage');

        properties[propertyKey] = value;
        $window.localStorage.setItem(localStorageId,
          JSON.stringify(properties));
      }
    }
}]);