function ClickWidget(layout, photos) {
  this.layout = layout;
  this.infoControl = new InfoControl();
  this.photosControl = new PhotosControl(this, photos);


  var _this = this;
  $('info-mask').addEvent('click', function() { _this.handleClick(); });
}

ClickWidget.prototype.handleClick = function() {
  window.open('http://www.brooklynmuseum.org/exhibitions/click', '_blank');
}


function InfoControl() {
  this.div = $("info");
  this.div.setOpacity(.8);

  this.divDefaultTop = parseInt(this.div.style.top);

  this.hovered = false;
  this.forceShow = false;
  this.tansitionDown = false;
  this.tansitionUp = false;

  var _this = this;
  // document.body.addEvent('mousemove', function() { _this.handleMouseMove(); });
  $('info-mask').addEvent('mouseenter', function() { _this.hover(); });
  $('info-mask').addEvent('mouseleave', function() { _this.unhover(); });

}

InfoControl.prototype.hover = function() {
  this.hovered = true;
  this.showInfo();
}

InfoControl.prototype.autoShow = function() {
  this.autoShowEnabled = true;
  this.showInfo();
}

InfoControl.prototype.unAutoShow = function() {
  this.autoShowEnabled = false;
  if(this.hovered) return;

  this.hideInfo();
}

InfoControl.prototype.showInfo = function() {
  if(this.transitionDown) {
    this.transitionDown.stop();
  }

  var _this = this;
  var options = {
    duration:300 
  };
  this.transitionUp = new Fx.Style('info', 'top', options);

  var begin = parseInt(this.div.style.top);
  // var infoHeight = Math.round(WIDGET_HEIGHT/3);
  var end = CONTROLS_SHOWN_TOP; // this.divDefaultTop - infoHeight;

  this.transitionUp.start(begin, end);
}

InfoControl.prototype.unhover = function() {
  this.hovered = false;
  if(this.autoShowEnabled) return;

  this.hideInfo();
}

InfoControl.prototype.hideInfo = function() {
  if(this.transitionUp) {
    this.transitionUp.stop();
  }

  var _this = this;
  var options = {
    duration:300 
  };
  this.transitionDown = new Fx.Style('info', 'top', options);

  var begin = parseInt(this.div.style.top);
  var end = CONTROLS_HIDDEN_TOP; // this.divDefaultTop;

  this.transitionDown.start(begin, end);
}


function PhotosControl(widget, photoPaths) {
  this.widget = widget;
  this.photoPaths = photoPaths;

  this.imgs = new Array();
  this.imgStates = {};

  this.logoImg = null;
  this.logoCopy = null;

  this.advanceDelay = 5000;
  this.fetchSize = 3;
  this.preloadBuffer = 1;

  // If photos
  if(this.photoPaths.length > 0) {

    var photosHolder = $('photos');

    // add logo as one of the photos
    for(var i=0;i<photosHolder.childNodes.length;i++) {
      if(photosHolder.childNodes[i].tagName=='IMG') {
        this.logoImg = photosHolder.childNodes[i];
        this.photoPaths.unshift(this.logoImg.src);
        this.imgs[this.imgs.length] = this.logoImg;
        this.imgStates[this.logoImg.src] = 'loaded';
      }
    }

    // Start carousel
    this.index = -1;
    this.fetchNext();
    this.advance();

  // No photos
  } else {

    // Show info bar and lock it
    this.widget.infoControl.autoShow();
  }
}

PhotosControl.prototype.notifyImgLoaded = function(img) {
  this.imgStates[img.src] = 'loaded';
  var width = parseInt($('photos').style.width);
  // $('photos').style.width = 
  var newWidth = width + img.width + PHOTO_HORIZ_PADDING + 'px';
  $('photos').style.width = newWidth;

  // dbg(img.src + ' loaded');
}

PhotosControl.prototype.hasPreloadedImgs = function(count) {
  for(var i=this.index+1;i<this.index+1+count;i++) {
    if(i >= this.imgs.length) {
      break;
    }
    var img = this.imgs[i];
    if(this.imgStates[img.src] != 'loaded') {
      // dbg('img at ' + i + ' not preloaded: ' + img.src + ', so not suff. preloaded');
      return false;
    }
  }

  return true;
}

PhotosControl.prototype.getImageByPath = function(path) {
  for(var i=0;i<this.imgs.length;i++) {
    if(this.imgs[i].src == path) {
      return this.imgs[i];
    }
  }
  return false;
}

PhotosControl.prototype.fetchNext = function() {
  // dbg("fetching next, index " + this.index);
  for(var i=this.index+1;i<this.index+1+this.fetchSize;i++) {
    var photosHolder = $('photos');

    if(i >= this.photoPaths.length) {
      if(this.logoImg && !this.logoCopy) {
        this.logoCopy = this.logoImg.cloneNode(0);
        photosHolder.appendChild(this.logoCopy);
        this.imgs[this.imgs.length] = this.logoCopy;
      }
      break;
    }

    var path = this.photoPaths[i];

    if($defined(this.imgStates[path])) continue;

    this.imgStates[path] = 'loading';

    // var img = document.createElement("IMG");
    var img = new Element('img');
    img.setStyle('opacity', 0.4);
    photosHolder.appendChild(img);

    img.addEvent('load', function() { });

    img.addEvent('load', this.createPreloadNotification(img));
    img.addEvent('error', this.createLoadErrorNotification(img));
    img.src = PHOTO_BASE_URL + '/' + this.widget.layout + '/' + path;
    // dbg('adding image: ' + img.src);
    this.imgs[this.imgs.length] = img;


    // this.preloadImage(path);
  }
}

PhotosControl.prototype.createPreloadNotification = function(img) {
  var _this = this;
  return function() { _this.notifyImgLoaded(img); };
}

PhotosControl.prototype.createLoadErrorNotification = function(img) {
  var _this = this;
  return function () { _this.imgStates[img.src] = 'error'; };
}

PhotosControl.prototype.advance = function() {
  if(this.hasPreloadedImgs(1)) {
    var photosHolder = $('photos');

    this.index++;
    if(this.index >= this.imgs.length) {
      this.index = 0;
    }

    // dbg('advancing: ' + this.index);

    if(this.index > 0) {
      // Transition:
      var _this = this;
      var config = {
        duration:500,
        transition: Fx.Transitions.Circ.easeInOut /*,
        onComplete: function() {
          if(_this.index == _this.imgs.length-1) {
            dbg("last");
          }
        }*/
      };
      var transition = new Fx.Style('photos', 'margin-left', config);
      var begin = this.index>0?this.getMidPosition(this.index-1):0;
      var end = this.getMidPosition(this.index);

      begin -= Math.round(WIDGET_WIDTH / 2);
      end -= Math.round(WIDGET_WIDTH / 2);

      transition.start(-1 * begin, -1 * end);

      var transition = new Fx.Style(this.imgs[this.index], 'opacity', config);
      transition.start(0.4, 1);
      
      if(this.index > 1) {
        var previousImg = this.imgs[this.index-1];
        if(previousImg) {
          var transition = new Fx.Style(previousImg, 'opacity', config);
          transition.start(1, 0.4);
        }
      }

      /*
      if(this.index>=2) {
        var previousImg = this.imgs[this.index-1];
        var transition = new Fx.Style(previousImage, 'opacity', config);
        transition.start(1, 0.5)
      }
      */

      // this.imgs[this.index].setStyle('opacity', 0.5);
    }

    // If first run (0) or final splash image (1+number of photo paths), show
    if(this.index == 0 || this.index==this.photoPaths.length) {
      this.widget.infoControl.autoShow();

    } else if(this.index == 1) {
      this.widget.infoControl.unAutoShow();
    }

    var _this = this;
    setTimeout(function() { _this.advance() }, this.advanceDelay);

    // If two more images, preload next
    if(this.index % this.fetchSize == (this.fetchSize-this.preloadBuffer)) {
      this.fetchNext();
    }

  } else {
    var _this = this;
    dbg('waiting to advance. imgs count: ' + this.imgs.length);

    var count = 1;
    for(var i=this.index+1;i<this.index+1+count;i++) {
      if(i >= this.imgs.length) {
        break;
      }
      var img = this.imgs[i];
      if(this.imgStates[img.src] != 'loaded') {
        dbg('img at ' + i + ' not preloaded: ' + img.src + ', so not suff. preloaded');
        return;
      }
    }

    setTimeout(function() { _this.advance() }, 2000);
  }
}

PhotosControl.prototype.getMidPosition = function(imgIndex) {
  var x = 0;
  for(var i=0;i<imgIndex;i++) {
    x += this.imgs[i].width;
    x += PHOTO_HORIZ_PADDING;
  }

  x += Math.round(this.imgs[imgIndex].width / 2);

  return x;
}


function dbg(str) {
  if(!$('dbg_div')) {
    var dbg_div = document.createElement("DIV");
    dbg_div.id = 'dbg_div';
    dbg_div.style.border = 'solid gray 1px';
    dbg_div.style.marginTop = '250px';
    dbg_div.style.width = '800px';
    dbg_div.style.fontSize = '11px';
    document.body.appendChild(dbg_div);
  } 
 
  // escape html 
  str = str.replace(/</g, '&lt;');
  str = str.replace(/>/g, '&gt;');

  $('dbg_div').innerHTML += "- " + str + '<br/>';
}



