function GoogleStorage(app, url) {
  if (!app) {
    throw "Application parameter missing"
  }
   if (!url) {
    throw "URL parameter missing"
  }
  this.app = app;
  this.url = url;
  this.storage = new Object();
  this.stack = new Array();
  this.stopped = false;
  this.user = null;
  var _self = this;
  
  var sendCode = function(url) {
    var code = document.getElementById("GoogleStorageCode");
    if (code) {
      code.parentNode.removeChild(code);
    }
    var body = document.getElementsByTagName("body")[0];
    code = document.createElement("script");
    code.id = "GoogleStorageCode";
    code.src = _self.url + url;
    code.type = "text/javascript";
    code.onerror = function() {
      if (_self.onError) {
        _self.onError("Error loading script");
      }
      _self.stopped = true;
    }
    body.appendChild(code);
  }
  
  this.sendItem = function(item) {
    this.stack.push(item);
    if (_self.stack.length < 2 || this.stopped) {
      this.sendNext();
    }      
  }
  
  this.onCheckLogin = null;
  
  this.checkLogin = function(url, onCheckLogin) {
    this.onCheckLogin = onCheckLogin;
    if (!url) {
      url = location.href;
    }
    sendCode("/check?url=" + encodeURIComponent(url));    
  }
  
  GoogleStorage.checkLoginResult = function(login, url, user) {
    if (_self.onCheckLogin) {
      _self.stack = new Array();
      _self.user = user;
      _self.onCheckLogin(login, url);
    }
    if (login.error && _self.onError) {
      _self.onError(result.error);
    }
  }
  
  this.sendLogout = function(url, onLogout) {
    if (!url) {
      url = location.href;
    }
    if (onLogout) {
      onLogout();
    }
    else {
      sendCode("/logout?url=" + url);
    }      
  }

  GoogleStorage.logoutResult = function(result, url) {
    if (result.error && _self.onError) {
      _self.onError(result.error);
    }
    if (url) {
      location.href = _self.url + url;      
    }
  }
  
  this.onReload = null;
  
  this.reload = function(onReload) {
    if (!this.user) {
      throw "No User";
    }
    this.storage = new Object();
    this.onReload = onReload;    
    sendCode("/retrieveAll?app=" + this.app);        
  }
  
  GoogleStorage.retrieveAllResult = function(result) {
    if (result.error && _self.onError) {
      _self.onError(result.error);
    }
    if (result.data) {
      for (var i = 0; i < result.data.length - 1; i++) {
      	_self.storage[result.data[i].key] = result.data[i].value; 
      }
    }
    if (_self.onReload) {
      _self.onReload(!result.error);
    }      
  }
  
  this.sendNext = function() {
    if (_self.stack.length > 0) {
      _self.stopped = false;
      var item = _self.stack[0];
      if (item.code == "send") {
        _self.send(item.key, item.value);
      }  
      if (item.code == "remove") {
        _self.sendRemove(item.key);
      }  
      if (item.code == "removeAll") {
        _self.sendRemoveAll(item.onRemoveAll);
      }  
      if (item.code == "logout") {
        _self.sendLogout(item.url, item.onLogout);
      }  
    }    
  }
  
  this.send = function(key, value) {
    sendCode("/put?app=" + encodeURIComponent(this.app) 
             + "&key=" + encodeURIComponent(key) 
             + "&value=" + encodeURIComponent(value));    
  }
  
  GoogleStorage.sendResult = function(result) {
    if (result.success) {
      _self.stack.shift();
      _self.sendNext();
    }
    else {
      _self.stopped = true;
    }
  }

  this.sendRemove = function(key) {
    sendCode("/remove?app=" + encodeURIComponent(this.app) 
             + "&key=" + encodeURIComponent(key));    
  }
  
  GoogleStorage.removeResult = function(result) {
    if (result.success) {
      _self.stack.shift();
      _self.sendNext();
    }
    else {
      _self.stopped = true;
    }
  }
  
  this.onRemoveAll = null;

  this.sendRemoveAll = function(onRemoveAll) {
    this.onRemoveAll = onRemoveAll;
    sendCode("/removeAll?app=" + encodeURIComponent(this.app));    
  }
  
  GoogleStorage.removeAllResult = function(result) {
    if (_self.onRemoveAll) {
      _self.onRemoveAll(result.success);
    }
    if (result.error && _self.onError) {
      _self.onError(result.error);
    }
    if (result.error) {
      _self.stopped = true;
    }
    else {
      _self.stack.shift();
      _self.sendNext();      
    }
  }
  
  this.store = function(key, value) {
    if (!this.user) {
      throw "No User";
    }
    this.storage[key] = value;
    var item = new Object;
    item.code = "send";
    item.key = key;
    item.value = value;
    this.sendItem(item);
  }
  
  this.get = function(key) {
    return this.storage[key];
  }
  
  this.remove = function(key) {
    if (!this.user) {
      throw "No User";
    }
    delete this.storage[key];
    var item = new Object;
    item.code = "remove";
    item.key = key;
    this.sendItem(item);
  }
  
  this.removeAll = function(onRemoveAll) {
    if (!this.user) {
      throw "No User";
    }
    this.storage = new Object();
    var item = new Object;
    item.code = "removeAll";
    item.onRemoveAll = onRemoveAll;
    this.sendItem(item);  
  }
  
  this.logout = function(url, onLogout) {
    if (!this.user) {
      throw "No User";
    }
    item = new Object();
    item.code = "logout";
    item.url = url;
    item.onLogout = onLogout;
    this.sendItem(item);
  }
}
