
/**
 * The Box class provides an element, that will be visible as basic box with round
 * corners in the site's layout.
 */
var Box = new Class({
  Extends: Base,

  element:    null,
  container:  null,

  initialize: function(data, template) {
    this.parent(data, template);

    this.element = new Element('div', {
      'class':  'box',
      'styles': template.styles
    });

    if (template.addClasses)
      $each(template.addClasses, function(c) {
        this.element.addClass(c);
      }.bind(this));

    this.container = new Element('span');
    this.element.grab(this.container);

    if (template.dataPath)
      this.setContent(this.data[0]);

    this.element.grab(new Element('div', { 'class': 'corner-top-left' }));
    this.element.grab(new Element('div', { 'class': 'corner-top-right' }));
    this.element.grab(new Element('div', { 'class': 'corner-bottom-left' }));
    this.element.grab(new Element('div', { 'class': 'corner-bottom-right' }));

    this.hideIfEmpty();
  },

  setContent: function(value) {
    this.container.set('html', parser.parseContent(translate(value)));
    this.hideIfEmpty();
  },

  hideIfEmpty: function() {
    if (isBlank(this.container.get('html')) && this.container.getChildren().length == 0) {
      this.element.setStyle('visibility', 'hidden');
    } else {
      this.element.setStyle('visibility', 'visible');
    }
  },

  toElement: function() {
    return this.element;
  }

});

/**
 * The MultiBox class inhiert from Box class, but provides more sturctured content.
 * The content can be (in that order): a picture, a headline, a teaser, a text and
 * a teaser link. All that content items are optinal - so the MultiBox can be
 * also used to show just a text or a teaser.
 */
var MultiBox = new Class({
  Extends: Box,

  initialize: function(data, template) {
    this.parent(data, template);

    this.element.addClass('multi_box');
    this.container.set('html', null);

    var picture   = jsonPath(this.data[0], template.pictureDataPath);
    var headline  = jsonPath(this.data[0], template.headlineDataPath);
    var teaser    = jsonPath(this.data[0], template.teaserDataPath);
    var text      = jsonPath(this.data[0], template.textDataPath);

    if (!isBlank(picture)) {
      this.container.grab(new Element('img', { src: 'content/' + pickFirst(picture).url }));
    }

    if (!isBlank(headline)) {
      this.container.grab(new Element('h1', { html: translate(pickFirst(headline)) }));
    }

    if (!isBlank(teaser)) {
      this.container.grab(new Element('span', {
        html: parser.parseContent(parser.parseTeaser(translate(pickFirst(teaser))))
      }));
    }

    if (!isBlank(text)) {
      this.container.grab(new Element('span', {
        html: parser.parseContent(translate(pickFirst(text)))
      }));
    }

    if (template.teaserLink) {
      var text  = template.teaserLink.text ? translate(template.teaserLink.text) : translate('mehr');
      var route = template.teaserLink.route;
      var value = template.teaserLink.value ?
                    template.teaserLink.value : (
                    template.teaserLink.valueDataPath ?
                      jsonPath(this.data[0], template.teaserLink.valueDataPath)[0] :
                      this.data[0]
                    );
      this.container.grab(new Element('span', {
        'class':  'clickable',
        'html':   ' ...&nbsp;' + text + '&nbsp;&gt;',
        'events': {
          'click': site.navigate.pass(route + '/' + value, site)
        }
      }));
      this.container.grab(new Element('br'));
      this.element.onclick = site.navigate.pass(route + '/' + value, site);
    }

    this.hideIfEmpty();
  }

});

/**
 * The MediaBox class provides a very specific box element. It assume, that the base
 * data object has three member arrays named 'pictures', 'sounds' and 'videos'. These
 * information is used to generate a box where the user can switch between all these
 * media elements. If pictureContentId is defined inside the template, the corresponding
 * box will be filled extra information text, if a picture is selected by the user.
 */
var MediaBox = new Class({
  Extends: Box,

  pictures:             [ ],
  sounds:               [ ],
  videos:               [ ],
  selectedPictureIndex: 0,

  pictureButtons:       [ ],
  soundButtons:         [ ],
  videoButtons:         [ ],

  contentElement:       null,
  contentBox:           null,

  initialize: function(data, template) {
    this.parent(data, template);

    this.element.addClass('media_box');
    this.container.set('html', null);

    this.pictures = jsonPath(this.data[0], template.picturesDataPath);
    this.sounds   = jsonPath(this.data[0], template.soundsDataPath);
    this.videos   = jsonPath(this.data[0], template.videosDataPath);

    // save the contentBox if contentBoxId is provided
    if (template.contentBoxId)
      this.contentBox = idMap.get(template.contentBoxId);

    this.createBar(template);

    if (this.pictures)
      this.selectPicture(0);
    else if (this.sounds)
      this.selectAudio(0);
    else if (this.videos)
      this.selectVideo(0);

    this.hideIfEmpty();
  },

  createBar: function(template) {
    var context = this;
    var bar = new Element('div', { 'class': 'bar' });

    if (this.pictures) {
      bar.grab(new Element('span', { 'class': 'label', 'html': 'Photo' }));
      bar.grab(new Element('span', {
        'class': 'clickable',
        'html': '&lt;',
        'events': {
          'click': this.selectPrevPicture.bind(context)
        }
      }));
      bar.grab(new Element('span', {
        'class': 'clickable',
        'html': '&gt;',
        'events': {
          'click': this.selectNextPicture.bind(context)
        }
      }));
      $each(this.pictures, function(picture, index) {
        this.pictureButtons[index] = new Element('span', {
          'class': 'clickable',
          'html': index + 1,
          'events': {
            'click': this.selectPicture.pass(index, context)
          }
        });
        bar.grab(this.pictureButtons[index]);
      }.bind(this));
    }

    if (this.sounds) {
      bar.grab(new Element('span', { 'class': 'label', 'html': 'Sound' }));
      $each(this.sounds, function(sound, index) {
        this.soundButtons[index] = new Element('span', {
          'class': 'clickable',
          'html': index + 1,
          'events': {
            'click': this.selectAudio.pass(index, context)
          }
        });
        bar.grab(this.soundButtons[index]);
      }.bind(this));
    }

    if (this.videos) {
      bar.grab(new Element('span', { 'class': 'label', 'html': "Video" }));
      $each(this.videos, function(video, index) {
        this.videoButtons[index] = new Element('span', {
          'id': 'video_link_' + index,
          'class': 'clickable',
          'html': index + 1,
          'events': {
            'click': this.selectVideo.pass(index, context)
          }
        });
        bar.grab(this.videoButtons[index]);
      }.bind(this));
    }

    this.container.grab(bar);
  },

  setContentElement: function(element) {
    if (this.contentElement) this.contentElement.dispose();
    this.contentElement = element;
    this.contentElement.fade('hide');
    this.container.grab(this.contentElement);
    this.contentElement.fade('in');
  },

  clearSelection: function() {
    if ($$('.media_box .selected'))
      $$('.media_box .selected').removeClass('selected');
  },

  selectPicture: function(index) {
    var image = this.imageElementForPicture(index);
    if (image == null)
      return;

    this.setContentElement(image);

    if (this.contentBox) {
      this.contentBox.setContent(this.pictures[index].content);
      this.contentBox.hideIfEmpty();
    }

    this.clearSelection();
    this.pictureButtons[index].addClass('selected');

    this.selectedPictureIndex = index;
  },

  selectPrevPicture: function() {
    if (this.selectedPictureIndex <= 0) return;
    this.selectPicture(this.selectedPictureIndex - 1);
  },

  selectNextPicture: function() {
    if (this.selectedPictureIndex >= this.pictures.length - 1) return;
    this.selectPicture(this.selectedPictureIndex + 1);
  },

  selectAudio: function(index) {
    // return if out of index
    if (index < 0 || index >= this.sounds.length) return;

    var image = this.imageElementForPicture(this.selectedPictureIndex);

    var audio = new Element('div', { 'class': 'audio' });
    if (Support.useFlashAudioPlayer()) {
      audio.set('style', 'height: 20px;');
      audio.set('html',
        '<object type="application/x-shockwave-flash" data="flash/player_mp3_maxi.swf" width="435" height="20">' +
        '  <param name="movie" value="flash/player_mp3_maxi.swf" />' +
        '  <param name="FlashVars" value="width=435&mp3=content/' + this.sounds[index].url + '&autoplay=1&showvolume=1" />' +
        '</object>');
    } else {
      audio.set('style', 'height: 32px;');
      audio.set('html',
        '<audio preload="auto" controls="true" autobuffer="true">' +
        '  <source src="content/' + this.sounds[index].url + '" type="audio/mpeg" />' +
        '</audio>');
    }

    var container = new Element('div');
    if (image)
      container.appendChild(image);
    container.appendChild(audio);

    this.setContentElement(container);

    if (this.contentBox)
      this.contentBox.setContent(this.sounds[index].content);

    this.clearSelection();
    this.soundButtons[index].addClass('selected');

    this.playAudio();
  },

  selectVideo: function(index) {
    // return if out of index
    if (index < 0 || index >= this.videos.length) return;
    var data = this.videos[index];

    var video = new Element('div', { 'class': 'video' });
    if (data.vimeo_id) {
      video.set('html', '<iframe src="http://player.vimeo.com/video/' + data.vimeo_id + '" width="435" height="326" frameborder="0"></iframe>');
    } else if (data.youtube_id) {
      video.set('html', '<iframe class="youtube-player" type="text/html" width="435" height="326" src="http://www.youtube.com/embed/' + data.youtube_id + '" frameborder="0"></iframe>');
    }

    this.setContentElement(video);

    if (this.contentBox)
      this.contentBox.setContent(this.videos[index].content);

    this.clearSelection();
    this.videoButtons[index].addClass('selected');
  },

  imageElementForPicture: function(index) {
    if (index < 0 || index >= this.pictures.length)
      return null;

    return new Element('img', {
      'src': 'content/' + this.pictures[index].url
    });
  },

  playAudio: function () {
    var audio = $$('div.audio > audio')[0];
    if (audio) {
      audio.load();
      audio.play();
    }
  }

});

/**
 * The CronBox uses an array projects to create a chronological list.
 */
var ChronBox = new Class({
  Extends: Box,

  initialize: function(data, template) {
    this.parent(data, template);

    this.element.addClass('chron_box');
    this.container.set('html', null);

    var projects = this.data.sort(function(a, b) {
      var timeDiff = extractDate(b) - extractDate(a);
      if (timeDiff != 0) return timeDiff;

      if (a.title < b.title) return -1;
      if (a.title > b.title) return 1;
      return 0;
    }.bind(this));

    var currentYear = null;
    $each(projects, function(project) {
      // if the next project has a date within another year, add the year as a headline
      var projectYear = extractDate(project).getFullYear();
      if (currentYear != projectYear) {
        this.container.grab(new Element('h1', { 'html': projectYear == 1900 ? 'Sonstige' : projectYear }));
        currentYear = projectYear;
      }

      this.container.grab(new Element('h2', { 'html': translate(project.title) }));
      this.container.grab(new Element('span', { 'html': parser.parseContent(translate(project.description)) }));

      this.container.grab(new Element('span', {
        'class':  'clickable',
        'html':   '&nbsp;...&nbsp;' + translate('mehr') + '&nbsp;&gt;',
        'events': {
          'click': site.navigate.pass('project/' + project.name, site)
        }
      }));

    }.bind(this));

    this.hideIfEmpty();
  }

});

/**
 * The EventBox shows a list of upcoming event.
 */
var EventBox = new Class({
  Extends: Box,

  initialize: function(data, template) {
    this.parent(data, template);

    this.element.addClass('event_box');
    this.container.set('html', null);

    var headline  = jsonPath(this.data[0], template.headlineDataPath);
    var text      = jsonPath(this.data[0], template.textDataPath);
    var items     = jsonPath(this.data[0], template.itemsDataPath);

    if (headline)
      this.container.grab(new Element('h1', { 'html': translate(pickFirst(headline)) }));

    if (text)
      this.container.grab(new Element('span', { 'html': parser.parseContent(translate(pickFirst(text))) }));

    if (items) {
      items = pickFirst(items).sort(function(a, b) {
        var timeDiff = extractDate(b) - extractDate(a);
        if (timeDiff != 0) return timeDiff;
      });
      items = template.shortListing ? items.slice(0, 3) : items
      $each(items, function(item) {
        var p = new Element('p');
        p.grab(new Element('span', { 'class': 'date', 'html': dateFormat(item.date, "dd.mm.yy") } ));
        p.grab(new Element('span', { 'class': 'text', 'html': parser.parseContent(translate(item.text)) } ));
        this.container.grab(p);
      }.bind(this));
    }

    if (template.shortListing) {
      var text  = translate('mehr');
      this.container.grab(new Element('span', {
        'class':  'clickable',
        'html':   ' ...&nbsp;' + text + '&nbsp;&gt;',
        'events': {
          'click': site.navigate.pass('page/events', site)
        }
      }));
      this.container.grab(new Element('br'));
    }

    this.hideIfEmpty();
  }

});

/**
 * The TextBox shows two texts, specified as array of two json paths in the .dataPaths property
 */

var TextBox = new Class(
    {
        Extends: Box,

        initialize: function(data, template) {
            this.parent(data, template);

            this.element.addClass('text_box');

            var teaser = parser.parseContent(translate(pickFirst(jsonPath(this.data[0], template.dataPaths[0]))));
            var text = parser.parseContent(translate(pickFirst(jsonPath(this.data[0], template.dataPaths[1]))));

            var body;
            if (teaser) {
                body = "<span class='teaser'>" + teaser + "</span> ";
            }
            if (text) {
                body += text;
            }

            if (body) {
                this.container.grab(new Element('p', { 'html': body}));
            }

            this.hideIfEmpty();
        }
    });

