


var Shoutbox = Class.create({
  postUrl: 'ajax/postShoutboxMessage.php',
  getUrl: 'ajax/getShoutboxMessages.php',

  initialize: function(container, options) {

    this.options = Object.extend({
      showSticky: false,
      newMessagesOnTop: true,
      newResponsesOnTop: false,
      immediatlyShowReplyForm: false,
      hideFormAfterPost: true,
      /*alsoToggleResponsesOnReply: false*/
      toggleContentOnClick: false
    }, options || {} );

	
    this.container = $(container);
    this.firstPaint = true;
  },


  lastTime: null,


  messages: [],


  doAutomaticUpdate: false,
  updateTimeoutId: false,
  updateInterval: 10000,

  processMessages: function(messages) {
    var element = this.getMessagesElement();
    if (this.firstPaint) {
      this.firstPaint = false;
      element.update();
    }
    messages.parentIds.each(function(parentId) {
      if (parentId) element = $('responses_' + parentId);
      if (element) {
        var reverseOrder = parentId ? !this.options.newResponsesOnTop : !this.options.newMessagesOnTop;

        messages.idAssignments[parentId].each(function(messageId) {
          if (this.messages[messageId]) {
          // already processed
          } else {
            var messageElement = (this.getMessageNode(messages['messages'][messageId]));
            if (!reverseOrder) element.insert({
              top: messageElement
            });
            else               element.appendChild(messageElement);
          }
        }, this);
      }
    }, this);
    this.messages = Object.extend(this.messages, messages['messages']);//.push(messages['messages']);
  },


  getMessageNode: function(message) {
    var self = this;
    var hideContent = (this.options.toggleContentOnClick);
    var element = Builder.node('div', {
      className: 'wrapper '+messageTypes[message.typeId]+'Content'+(message.parentId ? '' : ' topLevelContent')+(message.authorName.toLowerCase() == 'ginga' ? ' gingaWrapper' : '')
    }, [
    Builder.node('div', {
      className: 'header'
    }, [
    Builder.node('span', {
      className: 'authorName'
    }, message.authorName),
    Builder.node('span', {
      className: 'creationTime'
    }, ' ' + message.creationTime)
    ])
    ]);
    var titleElement = element.appendChild(Builder.node('div', {
      className: 'title'
    }, Builder.node('div').update(message.title)));
    var textElement = Builder.node('div', {
      className: 'text'
    });
    textElement.update(Builder.node('p', Builder.node('div').update(message.text)));
    //		message.text.gsub(/([^\n]+)/, function(matches) {
    //			textElement.appendChild(Builder.node('p', Builder.node('div', matches[1]))); });
    element.appendChild(textElement);

    if (messageTypes[message.typeId] == 'video' && message.video) {
      var videoElement = Builder.node('div', {
        className: 'videoContainer ' + (message.video.isWidescreen ? 'widescreen' : 'normal') + (message.video.isHd ? ' hd' : '')
      }, Builder.node('div', {
        className: 'flashContainer'
      }));
      var videoImageElement = videoElement.appendChild(Builder.node('div', Builder.node('img', {
        src: 'pictures/spacer.gif',
        style: 'font-weight: bold; background-image: url(\'http://img.youtube.com/vi/' + message.video.videoId + '/0.jpg\');'
      })));

      videoImageElement.observe('click', function() {
        self.showVideo(message.video);
      });
			
      element.appendChild(videoElement);
    }
    if (messageTypes[message.typeId] == 'gallery') {
      var imagesElement = Builder.node('div', {
        className: 'imagesContainer'
      });
      message.images.each(function(image) {
        var link = Builder.node('a', {
          href: 'javascript:undefined',
          id: 'galleryImageLink_' + image.id
        }, Builder.node('img', {
          src: 'http://data.thisisginga.com/shoutbox/images/'+image.id+'.jpg'
        })).observe('click', function() {
          self.showGalleryImage(image.id);
        });
        link._imageId = image.id;
        imagesElement.appendChild(link);
      });

      element.appendChild(imagesElement);
    }
    if (messageTypes[message.typeId] == 'image') {
      var imagesElement = Builder.node('div', {
        className: 'imageContainer'
      });
      var image = message.images.first();
      if (image) {
        imagesElement.appendChild(Builder.node('img', {
          src: 'http://data.thisisginga.com/shoutbox/images/'+image.id+'.jpg'
        }));
      };

      element.appendChild(imagesElement);
    }
    element = Builder.node('div', {
      id: 'message_' + message.id,
      className: 'message ' + messageTypes[message.typeId]
    }, element);

    if (!message.parentId) {
      var link = Builder.node('a', {
        href: 'javascript:undefined;'
      }, 'reply').observe('click', function() {
        self.toggleForm('message_' + message.id, message.id);
      });
      if (!this.options.immediatlyShowReplyForm) {
        element.appendChild(Builder.node('div', {
          className: 'actions'
        },
        Builder.node('div', {
          className: 'reply'
        }, link)
        ));
      }
      if (messageTypes[message.typeId] != 'comment' && hideContent) {
        var commentSpan = Builder.node('div', {
          className: 'comments'
        },
        Builder.node('a', {
          href: 'javascript:none;'
        },
        [
        (message.childrenCount > 0 ? Builder.node('span', {
          className: 'commentCount'
        }, message.childrenCount) : ''),
        ' comment' + (message.childrenCount == 1 ? '' : 's')
          ]));
        element.appendChild(commentSpan);
      }

      var postFormContainer = element.appendChild(Builder.node('div', {
        className: 'postFormContainer'
      }));
      var responsesElement = element.appendChild(Builder.node('div', {
        className: 'responses',
        id: 'responses_' + message.id
      }));
      if (this.options.immediatlyShowReplyForm) {
        this.appendForm(postFormContainer, message.id);
      }
      if (hideContent) {
        if (messageTypes[message.typeId] == 'event') textElement.hide();
        responsesElement.hide();
        postFormContainer.hide();
        var toggleFunction = function() {
          if (messageTypes[message.typeId] == 'event') textElement.toggle();
          responsesElement.toggle();
          postFormContainer.toggle();
        }
        commentSpan.observe('click', toggleFunction);
        titleElement.observe('click', toggleFunction);
      //if (videoImageElement) videoImageElement.observe('click', toggleFunction);
      }
    }

    return element;
  },


  toggleForm: function(elementId, parentId) {
    if ($(elementId).down('.postFormContainer form')) {
      $(elementId).down('.postFormContainer').update();
    //			if (this.options.alsoToggleResponsesOnReply) $(elementId).down('.responses').setStyle({ display: 'none' });
    } else {
      this.showForm(elementId, parentId);
    //			if (this.options.alsoToggleResponsesOnReply) $(elementId).down('.responses').setStyle({ display: 'block' });
    }
  },
  showForm: function(elementId, parentId, hideAfterPost) {
    var element = $(elementId).down('.postFormContainer');
    element._hideAfterPost = hideAfterPost === undefined ? this.options.hideFormAfterPost : hideAfterPost;
    this.appendForm(element, parentId);
  },
  appendForm: function(element, parentId) {
    var nameElement     = Builder.node('input',    {
      className: 'authorName',
      type: 'text',
      value: ''
    });
    var passwordElement = Builder.node('input',    {
      className: 'authorPassword',
      type: 'password',
      value: ''
    });
    var messageElement  = Builder.node('textarea', {
      className: 'textarea',
      rows: 3,
      cols: 30
    });

    var formElement = (Builder.node('form', {
      action: 'javascript:undefined'
    }, [
    Builder.node('div', {
      className: 'name'
    }, [
    Builder.node('label', {
      htmlFor: nameElement.identify()
    }, 'your name'),
    nameElement
    ]),
    Builder.node('div', {
      className: 'password',
      style: 'display: none'
    }, [
    Builder.node('label', {
      htmlFor: passwordElement.identify()
    }, 'password'),
    passwordElement
    ]),
    Builder.node('div', {
      className: 'message'
    }, [
    Builder.node('label', {
      htmlFor: messageElement.identify()
    }, 'your message'),
    messageElement
    ]),
    Builder.node('button', {
      type: 'submit'
    } , 'enter')
    ]));
    var self = this;
    formElement.observe('submit', function() {
      self.postMessage(nameElement.getValue(), messageElement.getValue(), passwordElement.getValue(), parentId, element);
      return undefined;
    } );


    var checkForPassword = function(event) {
      if (event.element().getValue().match(/^\s*(g+i+n+g+a+|matthias\s*loitsch|[kc]lemens\s*wihlidal|alex\s*konrad|(emanuel|emi)\s*donner)\s*$/i)) {
        element.down('.password').show();
      }
      else {
        element.down('.password').hide();
      }
    };

    nameElement.observe('change', checkForPassword).observe('keyup', checkForPassword);

    element.update();
		
    element.appendChild(Builder.node('div', {
      className: 'success'
    }));
    element.appendChild(Builder.node('div', {
      className: 'error'
    }));
    element.appendChild(formElement);
  },


  updateMessages: function(updateCountParentId) {
    this.clearUpdateTimeout();
    var self = this;
    var parameters = { };
    if (this.lastTime)   parameters.after = this.lastTime;
    if (this.options.showSticky) parameters.sticky = true;

    new Ajax.Request(this.getUrl, {
      method: 'get',
      parameters: parameters,
      onSuccess: function(transport) {
        try {
          var messages = transport.responseText.evalJSON();
          self.lastTime = messages.time;
          self.processMessages(messages);
          if (updateCountParentId) self.updateCommentCount(updateCountParentId);
        }
        catch (e) {
          self.showError('ERROR: ' + e + ' ('+e.fileName+', '+e.lineNumber+')');
        }
        self.setUpdateTimeout();
      },
      onFailure: function() {
        self.showError('Something went wrong.');
        self.setUpdateTimeout();
      }
    });
  },

  setUpdateTimeout: function() {
    if (self.doAutomaticUpdate) {
      this.updateTimeoutId = setTimeout(this.updateMessages, this.updateInterval);
    }
  },

  clearUpdateTimeout: function() {
    clearTimeout(this.updateTimeoutId);
  },

  postMessage: function(authorName, message, password, parentId, formContainer)
  {
    if (authorName.empty() || message.empty()) {
      formContainer.down('.error').show().update('Please fill in all values.');
    }
    else
    {
      formContainer.down('form').disable();
      formContainer.down('button').hide();

      var self = this;

      new Ajax.Request(this.postUrl, {
        method: 'post',
        parameters: {
          authorName: authorName,
          message: message,
          password: password,
          parentId: parentId
        },

        onSuccess: function(transport) {
          if (formContainer._hideAfterPost) {
            formContainer.down('form').remove();
          }
          else {
            formContainer.down('form').enable().reset();
          }
          if (!transport.responseText.strip().empty()) {
            formContainer.down('.error').show().update('Something went wrong: ' + transport.responseText);
          }
          else {
            if (!formContainer._hideAfterPost) formContainer.down('button').show();
            formContainer.down('.error').hide().update();
            formContainer.down('.success').show().update('Thank you for your post.' + (parentId ? '' : '<br /><a href="javascript:shoutbox.showForm(\'shoutbox\', null);undefined;">Write another message</a><br /><br /><br />'));
            self.updateMessages(parentId);
          }
        },
        onFailure: function() {
          formContainer.down('.error').show().update.showError('Something went wrong... sorry');
        }
      });
    }
  },

  updateCommentCount: function(messageId) {
    var count = $('message_' + messageId).select('.message.comment').size(),
    commentCountElement = $('message_' + messageId).down('.commentCount');
        
    if (commentCountElement) commentCountElement.update(count);
  },

  showError: function(error)
  {
    var theElement = this.getErrorElement();
    theElement.update(error);
    theElement.show();
  },


  showGalleryImage: function(imageId) {
    if (Prototype.Browser.IE) {
      var version = navigator.userAgent.match('MSIE ([\\d.]+)');
      var IEVersion = version ? (parseFloat(version[1])) : false;
      if (IEVersion == 6) {
        window.open('http://data.thisisginga.com/shoutbox/images/big/' + imageId + '.jpg');
        return;
      }
    }

    var self = this;
    var nextFunction = null;
    var previousFunction = null;
    var nextImage = $('galleryImageLink_' + imageId).next('a');
    var previousImage = $('galleryImageLink_' + imageId).previous('a');
    if (nextImage)     {
      nextFunction     = function() {
        self.showGalleryImage(nextImage._imageId);
      }
    }
    if (previousImage) {
      previousFunction = function() {
        self.showGalleryImage(previousImage._imageId);
      }
    }
	
	
    var loadingElement = $(Builder.node('div', {
      className: 'loading'
    }, 'Loading...'));
    var imageElement = $(new Image());
    imageElement.hide();
    imageElement.onload = function() {
      imageElement.show();
      loadingElement.hide();
      Blackbox.centerContent();
    };
    imageElement.src = 'http://data.thisisginga.com/shoutbox/images/big/' + imageId + '.jpg';
		
		
		
    Blackbox.setContent(Builder.node('div', [ imageElement, loadingElement ]), previousFunction, nextFunction);
  },

  showVideo: function(video) {
    var width = 480;
    var height = video.isWidescreen ? 295 : 385;

    if (video.isHd) {
      width = 560;
      height = 340;
    }
    var flashContainer;
    var videoElement = Builder.node('div', {
      className: 'videoContainer',
      style: 'width: ' + width + 'px; height: ' + height + 'px'
    }, flashContainer = Builder.node('div'));
    Blackbox.setContent(videoElement, null, null, width);
    swfobject.embedSWF("http://www.youtube.com/v/" + video.videoId + "&fs=1", flashContainer.identify(), width, height, "8", null, null, null, null, function() {
      Blackbox.centerContent();
    });
  },

  getMessagesElement: function() {
    return this.container.down('.messages');
  },
  getFormElement    : function() {
    return this.container.down('.form form');
  },
  getErrorElement   : function() {
    return this.container.down('.form .error');
  },
  getSuccessElement : function() {
    return this.container.down('.form .success');
  }
});


