// ==Taberareloo==
// {
//   "name"        : "Google+ model"
// , "description" : "Post to Google+"
// , "include"     : ["background", "content", "popup"]
// , "match"       : ["https://plus.google.com/*"]
// , "version"     : "2.0.2"
// , "downloadURL" : "https://raw.github.com/taberareloo/patches-for-taberareloo/master/models/model.googleplus.tbrl.js"
// }
// ==/Taberareloo==

(function() {
  if (inContext('background')) {
    if (Models['Google+']) {
      if (Models['Google+'].timer) {
        clearTimeout(Models['Google+'].timer);
      }
      Models.remove('Google+');
    }

    Models.register({
      name       : 'Google+',
      ICON       : 'https://ssl.gstatic.com/s2/oz/images/faviconr3.ico',
      LINK       : 'https://plus.google.com/',
      LOGIN_URL  : 'https://plus.google.com/up/start/',

      HOME_URL   : 'https://plus.google.com/',
      BASE_URL   : 'u/0/',
      INIT_URL   : '_/initialdata',
      POST_URL   : '_/sharebox/post/',
      UPLOAD_URL : '_/upload/photos/resumable',
      SNIPPET_URL: '_/sharebox/linkpreview/',

      is_pages : false,

      sequence : 0,

      YOUTUBE_REGEX : /http(?:s)?:\/\/(?:.*\.)?youtube.com\/watch\?v=([a-zA-Z0-9_-]+)[-_.!~*'()a-zA-Z0-9;\/?:@&=+\$,%#]*/g,

      timer : null,

      initialize : function() {
        var self = this;

        if (this.timer) {
          clearTimeout(this.timer);
          this.timer = null;
        }

        if (this.is_pages) {
          return;
        }

        var enable = false;
        ['regular', 'photo', 'quote', 'link', 'video', 'favorite'].forEach(function (type) {
          var config = Models.getConfig({ type: type }, self);
          if ((config === 'default') || (config === 'enabled')) {
            enable = true;
          }
        });

        if (!enable) {
          return;
        }

        return getCookies('.google.com', 'SSID').then(function (cookies) {
          if (cookies.length) {
            try {
              self._getStreams();
            }
            catch (e) {}
          }
          else {
            self.streams = null;
          }
          self.timer = setTimeout(function () {
            self.initialize();
          }, 60000);
        });
      },

      check: function(ps) {
        return /regular|photo|quote|link|video/.test(ps.type);
      },

      getAuthCookie: function() {
        var that = this;
        return getCookies('.google.com', 'SSID').then(function (cookies) {
          if (cookies.length) {
            return cookies[cookies.length-1].value;
          } else {
            throw new Error(chrome.i18n.getMessage('error_notLoggedin', that.name));
          }
        });
      },

      getOZData : function() {
        var self = this;
        return this.getInitialData(1).then(function (oz1) {
          return self.getInitialData(2).then(function (oz2) {
            return {'1': oz1, '2': oz2};
          });
       });
      },

      getInitialData : function(key) {
        var self = this;
        var url = this.HOME_URL + this.BASE_URL + this.INIT_URL;
        return request(url + '?' + queryString({
          hl     : 'en',
          _reqid : this.getReqid(),
          rt     : 'j'
        }), {
          sendContent : {
            key : key
          }
        }).then(function (res) {
          var initialData = res.responseText.substr(4).replace(/(\\n|\n)/g, '');
          return Sandbox.evalJSON(initialData).then(function (json) {
            var data = self.getDataByKey(json[0], 'idr');
            if (!data) {
              throw new Error(chrome.i18n.getMessage('error_notLoggedin', self.name));
            }
            return Sandbox.evalJSON(data[1]).then(function (json) {
              return json[key];
            });
          });
        });
      },

      getDataByKey : function(arr, key) {
        for (var i = 0, len = arr.length ; i < len ; i++) {
          var data = arr[i];
          if (data[0] === key) {
            return data;
          }
        }
        return null;
      },

      getDefaultScope : function() {
        var self = this;
        return this.getInitialData(11).then(function(data) {
          if (!data) return JSON.stringify([]);

          data = data[15][2];

          var aclEntries = [];

          for (var i = 0, len = data.length ; i < len ; i++) {
            var scope = data[i];
            switch (scope[0][2]) {
            case 1:
              aclEntries.push({
                scopeType   : 'presets',
                name        : scope[1],
                id          : scope[0][2],
                me          : true,
                requiresKey : false
              });
              break;
            case 3:
              aclEntries.push({
                scopeType   : 'presets',
                name        : scope[1],
                id          : scope[0][2],
                me          : false,
                requiresKey : false,
                groupType   : 'a'
              });
              break;
            case 4:
              aclEntries.push({
                scopeType   : 'presets',
                name        : scope[1],
                id          : scope[0][2],
                me          : false,
                requiresKey : false,
                groupType   : 'e'
              });
              break;
            default:
              aclEntries.push({
                scopeType   : 'focusGroup',
                name        : scope[1],
                id          : scope[0][1],
                me          : false,
                requiresKey : false,
                groupType   : 'p'
              });
              break;
            }
          }

          return JSON.stringify(aclEntries);
        });
      },

      post : function(ps) {
        var self = this;
        ps = update({}, ps);
        return this.getAuthCookie().then(function (cookie) {
          return self.getOZData().then(function (oz) {
            return (ps.file ? self.upload(ps.file, oz) : Promise.resolve(null))
              .then(function(upload) {
              ps.upload = upload;
              return ((!self.is_pages && ps.scope)
                ? Promise.resolve(ps.scope) : self.getDefaultScope(oz))
                .then(function (scope) {
                ps.scope = scope;
                return self._post(ps, oz);
              });
            });
          });
        });
      },

      favor : function(ps) {
        return this.post(update({reshare : true}, ps));
      },

      getReqid : function() {
        var sequence = this.sequence++;
        var now = new Date;
        var seconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds();
        return seconds + sequence * 1E5;
      },

      getToken : function(oz) {
        return 'oz:' + oz[2][0] + '.' + Date.now().toString(16) + '.' + this.sequence.toString(16);
      },

      getSnippetFromURL : function(url, oz) {
        var self = this;
        var data = [];
        data.push(url);
        data.push(false, false);
        data.push(null, null, null, null, null, null, null, null, null);
        data.push(true);
        return request(this.HOME_URL + this.SNIPPET_URL + '?' + queryString({
          hl     : 'en',
          _reqid : this.getReqid(),
          rt     : 'j'
        }), {
          sendContent : {
            'f.req' : JSON.stringify(data),
            at      : oz[1][15]
          }
        }).then(function(res) {
          var initialData = res.responseText.substr(4).replace(/(\\n|\n)/g, '');
          return Sandbox.evalJSON(initialData).then(function (json) {
            var data = self.getDataByKey(json[0], 'lpd');
            return data;
          });
        });
      },

      makeSnippetPostable : function(snippet) {
        for (var i = 0, len = snippet.length ; i < len ; i++) {
          var item = snippet[i];
          if (Array.isArray(item)) {
            snippet[i] = this.makeSnippetPostable(item);
          }
          else if ((item !== null) && (typeof item === 'object')) {
            for(var key in item) {
              snippet[i][key] = this.makeSnippetPostable(item[key]);
            }
            for (var j = i ; j < 5 ; j++) {
              snippet.splice(i, 0, null);
            }
            break;
          }
        }
        return snippet;
      },

      createPhotoInfo : function (ps, oz) {
        var info = [];
        info.push(
          [344,339,338,336,335],
          null, null, null,
          [{"39387941":[true,false]}],
          null, null
        );
        info.push({
          "40655821": [
            ps.upload.pageUrl,
            ps.upload.url,
            ps.upload.mimeType,
            "",
            null, null, null,
            [], null, null,
            [], null, null,
            null, null, null, null, null,
            '' + ps.upload.width, '' + ps.upload.height,
            null, null, null, null, null,
            null,
            oz[2][0],
            null, null, null, null, null,
            null, null, null, null, null,
            ps.upload.albumid, ps.upload.photoid,
            queryString({
              albumid : ps.upload.albumid,
              photoid : ps.upload.photoid
            }),
            1,
            [],
            null, null, null, null, [],
            null, null, null, null, null,
            null, null, null, null, null,
            null, null, null, null, null,
            null, null, null, null, null,
            null, null, null, null, null,
            null, null, null, null, null,
            null, null, null, null, null,
            []
          ]
        });
        return info;
      },

      createScopeSpar : function(ps) {
        var aclEntries = [];

        var scopes = JSON.parse(ps.scope);

        if (scopes[0].scopeType === 'community') {
          return [[[null, null, null, [scopes[0].id]]]];
        }

        for (var i = 0, len = scopes.length ; i < len ; i++) {
          var scope = scopes[i];
          if (scope.scopeType == 'presets') {
            aclEntries.push([
              null, null, scope.id
            ]);
          }
          else {
            aclEntries.push([
              null, scope.id
            ]);
          }
        }

        return [aclEntries, null];
      },

      decodeHTMLEntities : function(str) {
        var div = $N('div');
        div.innerHTML = str;
        return div.innerText;
      },

      _post : function(ps, oz) {
        var self = this;
        return (
          (!ps.upload && !ps.reshare && (ps.type !== 'regular') && ps.pageUrl) ?
           this.getSnippetFromURL(ps.pageUrl, oz) :
           Promise.resolve()
        ).then(function (snippet) {
          var description = ps.description || '';
          if (ps.type === 'regular') {
            description = joinText([ps.item, ps.description], "\n");
          }
          var body = ps.body || '';
          ps.body = null;
          if (body) {
            body = body.replace(/\r\n/g, "\n");
            body = body.replace(/\n<br(\s*\/)?>/ig, "\n");
            body = body.replace(/<br(\s*\/)?>\n/ig, "\n");
            body = body.replace(/<br(\s*\/)?>/ig, "\n");
            body = body.trimTag().trim();
            body = self.decodeHTMLEntities(body);
            description = joinText([description, '“' + body + '”'], "\n\n");
          }
          if (ps.upload) {
            body = joinText([
              (ps.item || ps.page) ? '*' + (ps.item || ps.page) + '*' : '', ps.pageUrl,
              body ? '“' + body + '”' : ''], "\n");
            description = joinText([ps.description, body], "\n\n");
          }
          if (ps.tags && ps.tags.length) {
            var tags = ps.tags.map(function (tag) {
              return '#' + tag;
            }).join(' ');
            description = joinText([description, tags], "\n\n");
          }

          var data = [];
          if (ps.reshare) {
            data.push(
              ps.description || '',
              self.getToken(oz),
              ps.favorite.id,
              null, null, null,
              JSON.stringify([])
            );
          }
          else {
            data.push(
              description,
              self.getToken(oz),
              null,
              null, null, null,
              JSON.stringify([])
            );
          }

          data.push(null, null);
          var scopes = JSON.parse(ps.scope);
          data.push((scopes[0].scopeType !== 'community'));
          data.push([], false, null, null, [], null, false);
          data.push(null, null);
          data.push(null);
          data.push(null, null);
          data.push(null, null, null, null, null);
          data.push(false, false, false);
          data.push(null, null, null, null);
          if (ps.upload) {
            snippet = self.createPhotoInfo(ps, oz);
            data.push(snippet);
          }
          else {
            if (snippet) {
              var media_type;
              switch (snippet[4][0][0]) {
              case 1:
                media_type = 'link';
                break;
              case 2:
                media_type = 'video';
                break;
              default:
                media_type = 'link';
              }
              snippet = self.makeSnippetPostable(snippet[5][0]);
              if ((media_type !== 'video')) {
                var obj = snippet[5] || snippet[7];
                for (var key in obj) {
                  if (ps.type === 'photo') {
                    obj[key][1] = ps.itemUrl;
                    if (!obj[key][5]) {
                      obj[key][5] = [];
                      obj[key][5][1] = 150;
                      obj[key][5][2] = 150;
                    }
                    obj[key][5][0] = ps.itemUrl;
                    if (!obj[key][184]) {
                      obj[key][184] = [];
                      obj[key][184][0] = [339, 338, 336, 335, 0];
                      obj[key][184][5] = {40265033 : []};
                    }

                    function setImageToSnippet184(snippet184, image) {
                      snippet184[1] = image;
                      if (snippet184[5] && (typeof snippet184[5] === 'object')) {
                        for (var key in snippet184[5]) {
                          snippet184[5][key][0] = image;
                          snippet184[5][key][1] = image;

                          if (Array.isArray(snippet184[5][key][184])) {
                            setImageToSnippet184(snippet184[5][key][184], image);
                          }
                        }
                      }
                    }
                    setImageToSnippet184(obj[key][184], ps.itemUrl);
                  }
                  if (ps.type === 'quote') {
                    obj[key][1] = null;
                    obj[key][5] = null;
                    obj[key][7] = null;
                    obj[key][10] = null;
                    obj[key][184] = null;
                  }
                  obj[key][2] = ps.item || ps.page;
                  if (ps.type !== 'link') {
                    obj[key][3] = ps.body ? ps.body.trimTag().trim() : null;
                  }
                }
              }
              data.push(snippet);
            }
            else {
              data.push(null);
            }
          }
          data.push(null);

          if (scopes[0].scopeType === 'community') {
            data.push([[scopes[0].id, scopes[0].category]]);
          }
          else {
            data.push([]);
          }

          data.push(self.createScopeSpar(ps));

          data.push(null, null, null, null, null, null);

          var url = self.HOME_URL + self.BASE_URL + self.POST_URL;
          return request(url + '?' + queryString({
            hl     : 'en',
            _reqid : self.getReqid(),
            rt     : 'j'
          }), {
            sendContent : {
              'f.req' : JSON.stringify(data),
              at      : oz[1][15]
            }
          });
        });
      },

      openUploadSession : function(fileName, fileSize, oz) {
        var self = this;

        var data = {
          protocolVersion      : '0.8',
          createSessionRequest : {
            fields : [
              {
                external : {
                  name     : 'file',
                  filename : fileName,
                  put      : {},
                  size     : fileSize
                }
              },
              {
                inlined : {
                  name        : 'batchid',
                  content     : String(Date.now()),
                  contentType : 'text/plain'
                }
              },
              {
                inlined : {
                  name        : 'client',
                  content     : 'sharebox',
                  contentType : 'text/plain'
                }
              },
              {
                inlined : {
                  name        : 'disable_asbe_notification',
                  content     : 'true',
                  contentType : 'text/plain'
                }
              },
              {
                inlined : {
                  name        : 'streamid',
                  content     : 'updates',
                  contentType : 'text/plain'
                }
              },
              {
                inlined : {
                  name        : 'use_upload_size_pref',
                  content     : 'true',
                  contentType : 'text/plain'
                }
              },
              {
                inlined : {
                  name        : 'album_abs_position',
                  content     : '0',
                  contentType : 'text/plain'
                }
              }
            ]
          }
        };

        if (this.is_pages) {
          data.createSessionRequest.fields.push({
            inlined : {
              name        : 'effective_id',
              content     : oz[2][0],
              contentType : 'text/plain'
            }
          });
          data.createSessionRequest.fields.push({
            inlined : {
              name        : 'owner_name',
              content     : oz[2][0],
              contentType : 'text/plain'
            }
          });
        }

        var url = this.HOME_URL + this.UPLOAD_URL;
        return request(url + '?authuser=0', {
          sendContent  : JSON.stringify(data),
          responseType : 'json'
        }).then(function (res) {
          var session = res.response;
          if (session.sessionStatus) {
            return session;
          }
          return null;
        });
      },

      upload : function(file, oz) {
        return this.openUploadSession(file.name, file.size, oz).then(function (session) {
          if (!session) {
            throw new Error("Couldn't upload an image properly");
            return null;
          }
          return request(session.sessionStatus.externalFieldTransfers[0].putInfo.url, {
            mode         : 'raw',
            sendContent  : file,
            responseType : 'json'
          }).then(function (res) {
            var session = res.response;
            if (session.sessionStatus) {
              var completionInfo = session.sessionStatus
                .additionalInfo['uploader_service.GoogleRupioAdditionalInfo'].completionInfo;
              if (completionInfo && (completionInfo.status === 'SUCCESS')) {
                var pageUrl = 'https://plus.google.com/photos/' +
                  oz[2][0] + '/albums/' +
                  completionInfo.customerSpecificInfo.albumid + '/' +
                  completionInfo.customerSpecificInfo.photoid;
                completionInfo.customerSpecificInfo.pageUrl = pageUrl;
                return completionInfo.customerSpecificInfo;
              }
            }
            throw new Error("Couldn't upload an image properly");
            return null;
          });
        });
      },

      streams : null,

      getStreams : function() {
        return this.streams;
      },

      _getStreams : function() {
        var self = this;
        this.getInitialData(12).then(function (data) {
          var circles = [];
          if (data) {
            data[0].forEach(function (circle) {
              var code, id, name, has;
              id   = circle[0][0];
              name = circle[1][0];
              if (id && name) {
                has = false;
                circles.forEach(function (c) {
                  if (!has && c[0].id === id) {
                    has = true;
                  }
                });
                if (!has) {
                  circles.push([{
                    scopeType   : 'focusGroup',
                    name        : name,
                    id          : id,
                    me          : false,
                    requiresKey : false,
                    groupType   : 'p'
                  }]);
                }
              }
            });
          }

          var presets = [
            [{
              scopeType   : 'presets',
              name        : 'Your circles',
              id          : 3,
              me          : false,
              requiresKey : false,
              groupType   : 'a'
            }],
            [{
              scopeType   : 'presets',
              name        : 'Extended circles',
              id          : 4,
              me          : false,
              requiresKey : false,
              groupType   : 'e'
            }],
            [{
              scopeType   : 'presets',
              name        : 'Anyone',
              id          : 1,
              me          : true,
              requiresKey : false
            }]
          ];

          self.streams = {
            presets : presets,
            circles : circles
          };
        });
      },

      getPages : function() {
        var self = this;
        return this.getInitialData(104).then(function (data) {
          var pages = [];
          if (data && data[1] && data[1][1] && data[1][1][0]) {
            data[1][1][0].forEach(function (page) {
              if (page[0]) {
                pages.push({
                  id   : page[0][30],
                  name : page[0][4][3],
                  icon : page[0][3]
                });
              }
            });
          }
          return pages;
        });
      },

      getCommunities : function() {
        var communities = localStorage.getItem('google_plus_communities');
        if (communities) {
          communities = JSON.parse(communities);
        }
        else {
          communities = [];
        }
        return communities;
      },

      setCommunities : function(communities) {
        communities.sort(function (a, b) {
          if (b[0].name > a[0].name) return -1;
          if (b[0].name < a[0].name) return 1;
          return 0;
        });
        localStorage.setItem('google_plus_communities', JSON.stringify(communities));
      },

      getCommunityCategories : function(community_id) {
        var self = this;
        return this.getOZData().then(function (oz) {
          var url = self.HOME_URL + self.BASE_URL + '_/communities/readmembers';
          return request(url + '?' + queryString({
            hl     : 'en',
            _reqid : self.getReqid(),
            rt     : 'j'
          }), {
            sendContent : {
              'f.req' : JSON.stringify([community_id, [[4],[3]]]),
              at      : oz[1][15]
            }
          }).then(function (res) {
            var initialData = res.responseText.substr(4).replace(/(\\n|\n)/g, '');
            return Sandbox.evalJSON(initialData).then(function (json) {
              var data = self.getDataByKey(json[0], 'sq.rsmr');
              var categories = [];
              if (data && data[2] && data[2][2] && data[2][2][0]) {
                data[2][2][0].forEach(function (category) {
                  categories.push({
                    id   : category[0],
                    name : category[1]
                  });
                });
              }
              return categories;
            });
          });
        });
      },

      addCommunityCategory : function(url, title) {
        var self = this;

        var regex = url.match(/\/\/plus\.google\.com\/(?:u\/0\/)?communities\/(\d+)\/stream\/([^?]+)/);
        if (regex) {
          this.removeCommunityCategory(url, title, true);
          var communities = this.getCommunities();
          var name = title.replace(/ - Google\+$/, '');
          communities.push([{
            scopeType : 'community',
            name      : name,
            id        : regex[1],
            category  : regex[2]
          }]);
          TBRL.Notification.notify({
            title   : name,
            message : 'Added',
            timeout : 3
          });
          this.setCommunities(communities);
          return true;
        }

        regex = url.match(/\/\/plus\.google\.com\/(?:u\/0\/)?communities\/(\d+)$/);
        if (regex) {
          this.getCommunityCategories(regex[1]).then(function (categories) {
            self.removeCommunityCategory(url, title, true);
            var communities = self.getCommunities();
            var name = title.replace(/ - Google\+$/, '');
            categories.forEach(function (category) {
              communities.push([{
                scopeType : 'community',
                name      : name + ' - ' + category.name,
                id        : regex[1],
                category  : category.id
              }]);
            });
            TBRL.Notification.notify({
              title   : name,
              message : 'Added all categories',
              timeout : 3
            });
            self.setCommunities(communities);
          });
          return true;
        }

        return false;
      },

      removeCommunityCategoryById : function(id, category) {
        var communities = this.getCommunities();
        var _communities = [];

        var found = false;
        communities.forEach(function (community) {
          if (community[0].id == id) {
            if (category) {
              if (community[0].category == category) {
                found = true;
              }
              else {
                _communities.push(community);
              }
            }
            else {
              found = true;
            }
          }
          else {
            _communities.push(community);
          }
        });
        this.setCommunities(_communities);
        return found;
      },

      removeCommunityCategory : function(url, title, no_nitify) {
        var regex = url.match(/\/\/plus\.google\.com\/(?:u\/0\/)?communities\/(\d+)\/stream\/([^?]+)/);
        if (regex) {
          var found = this.removeCommunityCategoryById(regex[1], regex[2]);
          if (found && !no_nitify) {
            TBRL.Notification.notify({
              title   : title.replace(/ - Google\+$/, ''),
              message : 'Removed',
              timeout : 3
            });
          }
          return found;
        }

        regex = url.match(/\/\/plus\.google\.com\/(?:u\/0\/)?communities\/(\d+)$/);
        if (regex) {
          var found = this.removeCommunityCategoryById(regex[1]);
          if (found && !no_nitify) {
            TBRL.Notification.notify({
              title   : title.replace(/ - Google\+$/, ''),
              message : 'Removed all categories',
              timeout : 3
            });
          }
          return found;
        }

        return false;
      }
    }, 'Diigo', true);

    Models.googlePlusPages = [];
    Models.getGooglePlusPages = function() {
      Models.removeGooglePlusPages();
      return Models['Google+'].getPages().then(function (pages) {
        return pages.reverse().map(function (page) {
          var model = update({}, Models['Google+']);
          model.name     = 'Google+ Page - ' + page.name;
          model.ICON     = 'http:' + page.icon;
          model.typeName = 'Google+';
          model.BASE_URL = 'b/' + page.id + '/';
          model.is_pages = true;
          Models.register(model, 'Google+', true);
          Models.googlePlusPages.unshift(model);
          return model;
        }).reverse();
      }).catch(function (e) {
        alert('Google+ Pages'+ ': ' +
          (e.hasOwnProperty('status') ? '\n' + ('HTTP Status Code ' + e.status).indent(4) : '\n' + e.message.indent(4)));
      });
    };
    Models.removeGooglePlusPages = function() {
      Models.googlePlusPages.forEach(function (model) {
        Models.remove(model);
      });
      Models.googlePlusPages = [];
    };

    setTimeout(function() {
      Models['Google+'].initialize();
      Models.getGooglePlusPages();
    }, 1000);

    var googlePlusCommunitiesURLs = [
      'https://plus.google.com/communities/*',
      'https://plus.google.com/u/0/communities/*'
    ];
    Menus._register({
      type: 'separator',
      contexts: ['all'],
      documentUrlPatterns: googlePlusCommunitiesURLs
    });
    Menus._register({
      title: 'Google+ Community ...',
      contexts: ['all'],
      documentUrlPatterns: googlePlusCommunitiesURLs
    });
    Menus._register({
      title: 'Add to destinations',
      contexts: ['all'],
      documentUrlPatterns: googlePlusCommunitiesURLs,
      onclick: function (info, tab) {
        chrome.tabs.sendMessage(tab.id, {
          request: 'contextMenusAddGooglePlusCommunityCategory',
          content: info
        });
      }
    }, 'Google+ Community ...');
    Menus._register({
      title: 'Remove from destinations',
      contexts: ['all'],
      documentUrlPatterns: googlePlusCommunitiesURLs,
      onclick: function (info, tab) {
        chrome.tabs.sendMessage(tab.id, {
          request: 'contextMenusRemoveGooglePlusCommunityCategory',
          content: info
        });
      }
    }, 'Google+ Community ...');
    Menus.create();

    TBRL.setRequestHandler('addGooglePlusCommunityCategory', function (req) {
      var ps = req.content;
      Models['Google+'].addCommunityCategory(ps.pageUrl, ps.page);
    });
    TBRL.setRequestHandler('removeGooglePlusCommunityCategory', function (req) {
      var ps = req.content;
      Models['Google+'].removeCommunityCategory(ps.pageUrl, ps.page);
    });
    return;
  }

  if (inContext('content')) {
    TBRL.setRequestHandler('contextMenusAddGooglePlusCommunityCategory', function (req, sender, func) {
      func({});
      var ctx = update({
        contextMenu: true
      }, TBRL.createContext(TBRL.getContextMenuTarget()));
      chrome.runtime.sendMessage(TBRL.id, {
        request: 'addGooglePlusCommunityCategory',
        show   : false,
        content: {
          page    : ctx.title,
          pageUrl : ctx.href
        }
      }, function () { });
    });
    TBRL.setRequestHandler('contextMenusRemoveGooglePlusCommunityCategory', function (req, sender, func) {
      func({});
      var ctx = update({
        contextMenu: true
      }, TBRL.createContext(TBRL.getContextMenuTarget()));
      chrome.runtime.sendMessage(TBRL.id, {
        request: 'removeGooglePlusCommunityCategory',
        show   : false,
        content: {
          page    : ctx.title,
          pageUrl : ctx.href
        }
      }, function () { });
    });
    return;
  }

  if (inContext('popup')) {
    var background = chrome.extension.getBackgroundPage();

    function Streams(posters, scope) {
      this.posters = posters;
      var container = this.container = $N('div', {id : 'streams'});
      var selectBox = this.selectBox = $N('select', {
        id: 'scope',
        name: 'scope',
        style: 'font-size:1em; width:100%; margin-bottom: 1em;',
        disabled: 'true'
      }, $N('option', {value : ''}, 'Not seem to log in Google+ (will check 1m later)'));
      container.appendChild(selectBox);
      $('widgets').appendChild(container);

      var streams = background.Models['Google+'].getStreams();
      var communities = background.Models['Google+'].getCommunities();
      if (streams) {
        $D(selectBox);
        selectBox.appendChild(
          $N('option', {value : '', selected : 'selected'}, 'Select Google+ Stream (or same as last one)')
        );
        if (streams && streams.presets.length) {
          for (var i = 0, len = streams.presets.length; i < len; i++) {
            var preset = streams.presets[i];
            selectBox.appendChild($N('option', {value : JSON.stringify(preset)}, preset[0].name));
          }
        }
        if (streams && streams.circles.length) {
          var optGroup = $N('optgroup', {label : 'Stream'});
          for (var i = 0, len = streams.circles.length; i < len; i++) {
            var circle = streams.circles[i];
            optGroup.appendChild($N('option', {value : JSON.stringify(circle)}, circle[0].name));
          }
          selectBox.appendChild(optGroup);
        }
        if (communities.length) {
          var optGroup = $N('optgroup', {label : 'Community Category'});
          for (var i = 0, len = communities.length; i < len; i++) {
            var category = communities[i];
            optGroup.appendChild($N('option', {value : JSON.stringify(category)}, category[0].name));
          }
          selectBox.appendChild(optGroup);
        }
        posters.hooks.push(function () {
          if (this.body().some(function (poster) { return poster.name === 'Google+'; })) {
            selectBox.removeAttribute('disabled');
            if (scope) {
              var savedScope = selectBox.querySelector('[value="' + scope.replace(/"/g, '\\"') + '"]');
              if (savedScope) {
                savedScope.selected = true;
              }
            }
          } else {
            selectBox.setAttribute('disabled', 'true');
          }
        });
        posters.postCheck();
      }
    }

    Streams.prototype = {
      constructor : Streams,
      body : function () {
        return this.selectBox.options[this.selectBox.selectedIndex].value;
      }
    };

    document.addEventListener('popupReady', function (ev) {
      var form = ev.detail;
      if (!form.streams) {
        form.savers.scope = form.streams = new Streams(form.posters, form.ps.scope);
      }
    }, false);
    return;
  }
})();