/* jshint eqnull:true browser:true */

//
// Twitch key/value storage interface
//
// Depends on twitch.core.js

(function(Twitch, $) {
  'use strict';

  /*
   * Twitch.storage interface. Stores and retrieves data from localStorage
   * or optionally from sessionStorage. If either of these APIs is not
   * available, all values will be stored and read from memory instead.
   *
   *     Twitch.storage.set('name', 'Jim');
   *     Twitch.storage.get('name'); // => 'Jim'
   *     Twitch.storage.del('name'); // blanks the value
   *
   *     Twitch.storage.set('name', 'Sam', {storage: 'sessionStorage'});
   *     Twitch.storage.get('name', {storage: 'sessionStorage'}); // => 'Sam'
   *
   *     Twitch.storage.setObject('name', {first: 'Nancy'});
   *     Twitch.storage.get('name'); // => '({ "first": "Nancy" })'
   *     Twitch.storage.getObject('name'); // => {first: "Nancy"}
   *     Twitch.storage.del('name'); // blanks the value
   *
   */

  var storage = {
    _buildMemoryStorage: function() {
      return {
        _storage: {},
        setItem: function(key, value) {
          this._storage[key] = value;
        },
        getItem: function(key) {
          return this._storage[key];
        },
        removeItem: function(key) {
          delete this._storage[key];
        }
      };
    },

    _localStorage: null,
    getLocalStorage: function() {
      if (this._localStorage === null) {
        try {
          var uid = new Date();
          (this._localStorage = window.localStorage).setItem(uid, uid);
          var fail = this._localStorage.getItem(uid) != uid;
          this._localStorage.removeItem(uid);
          fail && (this._localStorage = this._buildMemoryStorage());
        } catch (e) {
          this._localStorage = this._buildMemoryStorage();
        }
      }
      return this._localStorage;
    },

    _sessionStorage: null,
    getSessionStorage: function() {
      if (this._sessionStorage === null) {
        try {
          var uid = new Date();
          (this._sessionStorage = window.sessionStorage).setItem(uid, uid);
          var fail = this._sessionStorage.getItem(uid) != uid;
          this._sessionStorage.removeItem(uid);
          fail && (this._sessionStorage = this._buildMemoryStorage());
        } catch (e) {
          this._sessionStorage = this._buildMemoryStorage();
        }
      }
      return this._sessionStorage;
    },

    _storageForOptions: function(options) {
      if (options && options.storage === 'sessionStorage') {
        return this.getSessionStorage();
      }
      return this.getLocalStorage();
    },

    setObject: function(key, value, options) {
      this.set(key, JSON.stringify(value), options);
    },
    getObject: function(key, options) {
      var value = this.get(key, options);
      var parsed = null;
      if (value && value !== '') {
        try {
          parsed = JSON.parse(value);
        } catch (e) {}
      }
      return parsed;
    },

    set: function(key, value, options) {
      this._storageForOptions(options).setItem(key, value);
    },
    get: function(key, options) {
      return this._storageForOptions(options).getItem(key);
    },
    del: function(key, options) {
      this._storageForOptions(options).removeItem(key);
    }

  };

  /*
   * LEGACY. Only for existing usage, do not add new usage.
   *
   * Set, get and del values with cookies. Only strings can be stored.
   *
   *     Twitch.storage.legacy.set('name', 'Jill');
   *     Twitch.storage.legacy.set('name', 'Jill', seconds, path, domain);
   *
   *     Twitch.storage.legacy.get('name');
   *
   *     Twitch.storage.legacy.del('name');
   *     Twitch.storage.legacy.del('name', domain);
   *
   */

  storage.legacy = {};
  storage.legacy.set = function(name, value, seconds, path, domain) {
    var expires = '';
    if (!path) {
      path = "/";
    }
    if (seconds) {
      var date = new Date();
      date.setTime(date.getTime()+(seconds*1000));
      expires = "; expires="+date.toGMTString();
    }
    var cookie_str = name+"="+value+expires+"; path=" + path;
    if (domain == null) {
      // null domain == new-style (domain) cookies.
      document.cookie = cookie_str + "; domain=."+window.BaseDomain;
    } else if (domain === "") {
      // blank domain == old-style (host) cookies.
      document.cookie = cookie_str;
    }
  };

  storage.legacy.get = function(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
      var c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1,c.length);
      }
      if (c.indexOf(nameEQ) === 0) {
        return c.substring(nameEQ.length,c.length);
      }
    }
    return null;
  };

  storage.legacy.del = function(name, domain) {
    if(domain == null) {
      // delete both host (old-style) and domain (new-style) cookies!
      storage.legacy.set(name,"",-1); // new style (domain)
      storage.legacy.set(name,"",-1,null,""); // old style (host)
    } else {
      storage.legacy.set(name,"",-1,null,domain);
    }
  };

  Twitch.mixin({
    storage: storage
  });

})(window.Twitch, window.jQuery);
