Swivel.Feature = Class.create({
  initialize: function(options) {
    this._div = $(options.div);
    if (this._div.retrieve('feature')) { // bind only once
      return this._div.retrieve('feature').show();
    } else {
      this._div.store('feature', this);
    }

    this._groupId = options.groupId;
    this._assetType = options.assetType;
    this._callback = options.onSubmit || this._defaultCallback.bind(this);

    this._page = 1;
    this._setupObservers();

    // select current group
    var groupListItem = $('group_' + this._groupId);
    if (groupListItem)
      groupListItem.addClassName('selected');

    this.show();
    this._loadItems(this._page);
  },

  show: function() {
    if (!this._dialog)
      this._dialog = new Swivel.SheetDialog(this._div);
    else
      this._dialog.show();

    return this;
  },

  hide: function() {
    this._dialog.hide();
  },

  _setupObservers: function() {
    this._previous = this._div.down('button.previous').observe('click', this._previousPage.bind(this));
    this._next = this._div.down('button.next').observe('click', this._nextPage.bind(this));
    this._div.down('form.all').observe('submit', this._onSubmit.bindAsEventListener(this));
    Swivel.connect(this._dialog, '_hide', this, '_reset');

    this._groups = this._div.select('.groups li');
    if (this._groups)
      this._groups.invoke('observe', 'click',
        this._groupSelected.bindAsEventListener(this));

    var searchForm = this._div.down('form.search');
    if (searchForm)
      searchForm.observe('submit', this._search.bindAsEventListener(this));
  },

  _groupSelected: function(e) {
    var li = e.findElement('li');
    if (li.hasClassName('selected'))
      return;

    this._groups.invoke('removeClassName', 'selected');
    li.addClassName('selected');

    this._groupId = li.id.replace('group_', '')  // id is group_#
    this._lastPage = null;
    Form.Element.disable(this._previous);
    Form.Element.disable(this._next);

    this._loadItems(1);
  },

  _previousPage: function() {
    this._loadItems(--this._page);

    Form.Element.enable(this._next);
    if (this._page == 1) {
      Form.Element.disable(this._previous);
    }
  },

  _nextPage: function() {
    this._loadItems(++this._page);

    Form.Element.enable(this._previous);
    if (this._page == this._lastPage) {
      Form.Element.disable(this._next);
    }
  },

  _loadItems: function(page) {
    page = page || 1;  // page as in page 1, 2, 3 (NOT page, page_asset)
    this._div.down('.assets ul').update();
    this._div.down('.assets .loading').show();

    new Ajax.Request('/group_assets.js', {
      method: 'get',
      parameters: {
        group_id: this._groupId,
        'asset_type[]': $A(this._assetType),
        page: page
      },
      onSuccess: function(t) {
        if (!this._lastPage) {
          var contentRange = t.getHeader('Content-Range');
          if (contentRange) {
            this._lastPage = contentRange.match(/\/(\d+)/)[1];
            if (page < this._lastPage) {
              Form.Element.enable(this._next);
            }
          }
        }

        this._insertItems(t.responseText);
      }.bind(this)
    });
  },

  _insertItems: function(partial) {
    this._div.down('.assets .loading').hide();

    var ul = this._div.down('.assets ul').update(partial);
    this._list = ul.select('li')
      .invoke('observe', 'click', this._onClick.bindAsEventListener(this));
    this._list.zip(partial.evalScripts(), function(a) {
      a[0].store('json', a[1]);
    });
  },

  _reset: function() {
    if(this._list) this._list.invoke('removeClassName', 'selected');
    $('feature_thumbnail').down('img').src = '/images/blank.png';
  },

  _search: function() {
    new Ajax.Request('/search', {
      parameters: this._div.down('form.search').serialize(true),
      onLoading:function(request){
        this._div.select('.list_items ul').invoke('update')
        this._div.select('.list_items .loading').invoke('show');
      }.bind(this),
      onComplete: function(t) {
        this._insertItems(t.responseText);

        var groups = this._list.inject({}, function(h, li) {
          var ga = li.retrieve('json');
          var groupId = ga['group_id'];
          if (!h[groupId]) {
            h[groupId] = ga['group'] || { name: 'Public' };
            h[groupId].count = 1;
          } else {
            h[groupId].count++;
          }
          return h;
        }, this);

        this._div.down('.groups .loading').hide();
        var ul = this._div.down('.groups ul');

        // all
        ul.insert(new Element('li', { 'class': 'even selected' })
          .update('All <span class="minor">(' + this._list.length + ')</span>')
          .observe('click', function() {
            this._list.invoke('show');
            this._reStripe();
          }.bindAsEventListener(this))
        );

        $H(groups).each(function(pair, i) {
          var groupId = pair.key == 'null' ? null : pair.key;
          var li = new Element('li', { 'class': i & 1 ? 'even' : 'odd' })
            .update(pair.value.name + ' <span class="minor">('+pair.value.count+')</span>')
            .observe('click', function(e) {
              this._list.each(function(asset) {
                var ga = asset.retrieve('json');
                if (ga['group_id'] == groupId) {
                  asset.show();
                } else {
                  asset.hide();
                }
              }, this);
              this._reStripe();
            }.bindAsEventListener(this));
          ul.insert(li);
        }, this);

        ul.select('li').each(function(li) {
          li.observe('click', function(e) {
            ul.select('li').invoke('removeClassName', 'selected');
            li.addClassName('selected');
          });
        });
      }.bind(this)
    });
  },

  _reStripe: function() {
    this._list.select(function(li) { return li.visible(); }).each(function(li, i) {
      if (i & 1) { // odd
        li.removeClassName('even');
        li.addClassName('odd');
      } else { // even
        li.removeClassName('odd');
        li.addClassName('even');
      }
    });
  },

  _onClick: function(e) {
    this._asset = e.findElement('li');
    // toggle selected class
    this._list.invoke('removeClassName', 'selected');
    if (this._asset) {
      this._asset.addClassName('selected');
      this._div.select('input[type=submit]').invoke("enable");
    } else {
      this._div.select('input[type=submit]').invoke("disable");
    }

    // update preview image
    var preview = $('feature_thumbnail').down('img'),
        w = parseInt(preview.getStyle('width')),
        h = parseInt(preview.getStyle('height'));
    preview.src = this._asset.down('img').src.replace(/crop=\d+x\d+/,
        'crop=' + w + 'x' + h);

    // focus form
    this._div.down('.list + form').focusFirstElement();
  },

  _onSubmit: function() {
    if (!this._asset) {
      return;
    }

    var params = this._div.down('form').serialize(true);
    var ga = this._asset.retrieve('json');
    this._callback('/group_assets/' + ga['id'], params);
  },

  _defaultCallback: function(resourceUrl, params) {
    new Ajax.Request(resourceUrl, {
      method: 'put',
      parameters: params,
      onLoading: function() { $('feature_progress').appear(); },
      onSuccess: function() {
        window.location = this._groupId ? '/groups/' + this._groupId : '/public';
      }.bind(this)
    });
  }
});
