var Shop = Component.create({
  
  handleRate: function(element) {
    this.rates.append(element);
  },
  
  handleError: function(element) {
    if (/dialog/.test(element.className || ''))
      this.dialogs.append(element);
  }
});

Shop.define('login', {
    
  handleResponse: function(status) {
    if (status == 200)
      window.location.reload();
  },
  
  onSubmitElement: function(event) {
    event.preventDefault();
    this.request('POST', this.element.action, this.getParam());
  },
  
  getParam: function() {
    var o = {};
    o[this.password.name] = this.password.value;
    o[this.user.name]     = this.user.value;
    return o;
  }
});

Shop.define('dialogs', {

  append: function(element) {
    element.style.opacity = 0;
    this.insert(element);
    new Appearance(element);
  }
}).define('dialog', {

  run: function() {
    if (this.busy) {
      var notice = this;
      this.interval = setInterval(function() { notice.request('PUT', notice.path.href) }, 1000);
    } else if (this.notice || this.error || this.defnied) {
      this.waitAndRemove();
    }
  },
  
  update: function(notice) {
    if (notice.progress) {
      this.progress.innerHTML = notice.progress;
    }
    if (notice.progress == 100) {
      clearInterval(this.interval);
      this.waitAndRemove();
      this.request('DELETE', this.path.href);
    }
  },
  
  remove: function() {},
  
  waitAndRemove: function() {
    var element = this.element;
    
    setTimeout(function() {
      new FadeRemove(element);
    }, 3000);
  }
});

Shop.define('uploads', {
  
  run: function() {
    if (this.uploader)
      this.target = this.uploader.element;
  },
  
  uploadFrom: function(upload) {
    if (!this.uploading) {
      upload.form.submit();
      
      if (upload.path)
        this.request('GET', upload.path.href);
      
      this.uploading = upload;
    }
  },
  
  handleElement: function(element) {
    this.interface.dialogs.append(element);
  },
  
  onLoadTarget: function() {
    if (this.uploading) {
      this.uploading.update(this.uploader.getContent());
      this.uploading = false;
    }
  }
});

Shop.define('uploader', {
  
  getContent: function() {
    return this.getDocument().body.innerHTML;
  },
  
  getDocument: function() {
    return this.element.contentDocument || this.element.contentWindow.document;
  }
});

Shop.define('upload', {
  
  run: function() {
    this.image = this.element.getElementsByTagName('img')[0];
    this.form = this.form || this.element;
    
    this.file.value = '';
    
    if (/firefox\/3/i.test(navigator.userAgent)) {
      this.file.style.right = null;
      this.file.style.left  = 0;
    }
  },
  
  update: function(text) {    
    if (this.image) {
      this.element.removeChild(this.image);
    }
    this.image = document.loadFragment(text).firstChild;
    this.element.appendChild(this.image);

    this.removeName('busy');
  },
  
  onClickElement: function() {
    // Open the file browser (safari-only)
    this.file.click();
  },
  
  onChangeFile: function() {
    if (!this.image)
      return;
    
    this.addName('busy', this.element);
    this.uploads.uploadFrom(this);
    this.file.value = '';
  }
});


Shop.define('collection', {
  
  prepare: function() {
    this.items = [];
  },
  
  onClickAdd: function(event) {
    if (this.add.href) {
      this.request('POST', this.add.href);
    }
  },
  
  onClickExpand: function(event) {
    var collection = this;
    
    new AsyncRequest('GET', this.expand.href, {}, {
      handleResponse: function(code, text) {
        if (!text)
          return;

        var node = collection.document.loadFragment(text);
        
        collection.removeItems();
        collection.element.innerHTML = '';
        
        collection.context.insert(node);
        collection.element.appendChild(node);
      }
    }).send();
  },
  
  handleElement: function(element) {
    var item = this.context.insert(element).item;
    
    if (item) {
      this.element.appendChild(item.element);
      new Appearance(item.element);

      this.setNames();
    }    
  },
  
  removeItem: function(item) {
    var collection = this;
    
    collection.items.splice(item.position, 1);
    
    for (var i = item.position; i < this.items.length; i++) {
      this.items[i].position--;
    }
        
    new FadeRemove(item.element, function() {
      collection.setNames();
    });
  },
  
  moveForward: function(i) {
    var a = this.items[i], b = this.items[i + 1];
        
    this.element.insertBefore(b.element, a.element);
        
    a.position++;
    b.position--;
    
    this.items[i]     = b;
    this.items[i + 1] = a;
    
    this.setNames();
  },
  
  removeItems: function() {
    for (var i = 0; i < this.items.length; i++)
      this.element.removeChild(this.items[i].element || this.items[i]);
    this.items = [];
  },
  
  setNames: function() { return;
    if (this.items.length > 0) {
      this.setName('first', this.items[0].element);
      this.setName('last',  this.items[this.items.length - 1].element);
    }
  }
});

Shop.define('item', {
  
  run: function() {
    if (!this.collection)
      return;
    
    this.collection.items.push(this);
    this.position = this.collection.items.length;
    
    this.collection.setNames();
  },
  
  notifyWithCollection: function(component, container) {
    if (container)
      this.collection = this.collection || component;
  },
  
  remove: function() {
    this.collection.removeItem(this);
  },

  onClickBack: function(event) {
    if (this.position > 0) {
      this.collection.moveForward(this.position - 1);
    }
  },
  
  onClickForward: function(event) {
    if (this.position < this.collection.items.length - 1) {
      this.collection.moveForward(this.position);
    }
  },
  
  onClickDestroy: function(event) {
    if (confirm('Are you sure?')) {
      this.request('DELETE', this.destroy.href);
    }
  }
});

Shop.define('toPreview', {
  
  onClickElement: function(event) {
    this.interface.overlay.open();
  }  
});

Shop.define('overlay', {

  onClickElement: function(event) {
    this.hide();
  },
    
  open: function() {

    this.addName('overlayed', document.documentElement);
    this.addName('fixed', document.documentElement);

    this.interface.preview.makeCentered();

    var effect = new Effects.Opacity(this.element, { duration: 200 });
    
    effect.setStyle(this.element, 'opacity', 0);
    effect.custom(0, 0.6);
  },
  
  hide: function() {
    if (this.preview) this.preview.remove();
    
    var o = this;
    new Effects.Opacity(this.element, { duration: 200, onComplete: function() { o.removeName('overlayed'); o.removeName('fixed') } }).custom(0.6, 0);    
  }
});


Shop.define('preview', {
  
  onClickClose: function() {
    this.interface.overlay.hide();
  },
  
  makeCentered: function() {
    this.element.style.marginLeft = '-' + (this.element.offsetWidth / 2) + 'px';
    this.element.style.marginTop  = '-' + (this.element.offsetHeight / 2) + 'px';
  }
});

Shop.define('icon', {
  onClickElement: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue  = false;
      event.cancelBubble = true;
    }
  }
});

Shop.define('slideshow', {
  run: function() {
    var elements = this.element.getElementsByTagName('li');

    if (elements.length > 1) {
      this.items    = elements;
      this.index    = 0;
      this.selected = this.items[this.index];
      
      var object = this;
      this.inerval = setInterval(function() { object.onInterval() }, 5000);
    }
  },
  
  onClickDestroy: function(event) {
    new FadeRemove(this.element);
    for (var i = 0; i < page.articles.length; i++)
      page.articles[i].setModified();
    clearInterval(this.interval);
  },
  
  onInterval: function() {
    this.previous = this.selected;
    var selected = this.items[ this.index = ((this.index + 1) % this.items.length) ];

    this.removeName('selected');
    this.addName('selected', selected);
    
    this.fade(this.previous);
  },
  
  fade: function(element) {
    var slideshow = this;
    this.addName('fading', element);    

    new Effects.Opacity(element, { duration: 600, onComplete: function() {
      slideshow.removeName('fading');
      element.style.opacity    = null
      element.style.filter     = null;
      //element.style.visibility = null;
    } }).custom(1, 0);  
    
  }
});

var shop;
document.loadEvents.push(function() { shop = Shop.load(this.documentElement); })