/*
 *  popup.js
 *
 *  dependencies: prototype.js, effects.js, lowpro.js
 *
 *  --------------------------------------------------------------------------
 *  
 *  Allows you to open up a URL inside of a Facebook-style window. To use
 *  simply assign the class "popup" to a link that contains an href to the
 *  HTML snippet that you would like to load up inside a window:
 *  
 *    <a class="popup" href="window.html">Window</a>
 *
 *  You can also "popup" a specific div by referencing it by ID:
 *
 *    <a class="popup" href="#my_div">Popup</a>
 *    <div id="my_div" style="display:none">Hello World!</div>
 *  
 *  You will need to install the following hook:
 *  
 *    Event.addBehavior({'a.popup': Popup.TriggerBehavior()});
 *
 *  --------------------------------------------------------------------------
 *  
 *  Copyright (c) 2008, John W. Long
 *  Portions copyright (c) 2008, Five Points Solutions, Inc.
 *  
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *  
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *  
 */

var Popup = {
  BorderThickness: 8,
  BorderImage: '/images/popup_border_background.png',
  BorderTopLeftImage: '/images/popup_border_top_left.png',
  BorderTopRightImage: '/images/popup_border_top_right.png',
  BorderBottomLeftImage: '/images/popup_border_bottom_left.png',
  BorderBottomRightImage: '/images/popup_border_bottom_right.png'
};

Popup.borderImages = function() {
  return $A([
    Popup.BorderImage,
    Popup.BorderTopLeftImage,
    Popup.BorderTopRightImage,
    Popup.BorderBottomLeftImage,
    Popup.BorderBottomRightImage
  ]);
}

Popup.preloadImages = function() {
  if (!Popup.imagesPreloaded) {
    Popup.borderImages().each(function(src) {
      var image = new Image();
      image.src = src;
    });
    Popup.preloadedImages = true;
  }
}

Popup.TriggerBehavior = Behavior.create({
  initialize: function() {
    var href = this.element.getAttribute('href');
    var matches = href.match(/\#(.+)$/);
    if (matches) {
      this.window = new Popup.Window($(matches[1]));
    } else {
     this.window = new Popup.AjaxWindow(href);
    }
    if (this.element.hasClassName('now')) this.window.show();
  },
  
  onclick: function(event) {
    this.popup();
    event.stop();
  },
  
  popup: function() {
    this.window.show();
  }
});

Popup.AbstractWindow = Class.create({
  initialize: function() {
    Popup.preloadImages();
    this.buildWindow();
  },
  
  buildWindow: function() {
    this.element = new Element('table', {className: 'popup_window', style: 'display: none; position: absolute; border-collapse: collapse; padding: 0px; margin: 0px;'});
    var tbody = new Element('tbody');
    this.element.insert(tbody)
    
    var top_row = $tr();
    top_row.insert($td({style: 'background: url(' + Popup.BorderTopLeftImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; padding: 0px'}));
    top_row.insert($td({style: 'background: url(' + Popup.BorderImage + '); height: ' + Popup.BorderThickness + 'px; padding: 0px'}))
    top_row.insert($td({style: 'background: url(' + Popup.BorderTopRightImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; padding: 0px'}));
    tbody.insert(top_row);
    
    var content_row = $tr();
    content_row.insert($td({style: 'background: url(' + Popup.BorderImage + '); width: ' + Popup.BorderThickness + 'px; padding: 0px'}, ''));
    this.content = $td({style: 'background-color: white; padding: 0px'});
    content_row.insert(this.content);
    content_row.insert($td({style: 'background: url(' + Popup.BorderImage + '); width: ' + Popup.BorderThickness + 'px; padding: 0px'}, ''));
    tbody.insert(content_row);
    
    var bottom_row = $tr();
    bottom_row.insert($td({style: 'background: url(' + Popup.BorderBottomLeftImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; padding: 0px'}));
    bottom_row.insert($td({style: 'background: url(' + Popup.BorderImage + '); height: ' + Popup.BorderThickness + 'px; padding: 0px'}))
    bottom_row.insert($td({style: 'background: url(' + Popup.BorderBottomRightImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; padding: 0px'}));
    tbody.insert(bottom_row);

    var body = $$('body').first();
    body.insert(this.element);
  },
  
  makeDraggable: function() {
    if (!this.draggable)
      this.draggable = new Draggable(this.element.identify(), {handle: 'h3.title', scroll: window});
  },
  
  show: function() {
    this.beforeShow();
    this.element.show();
    this.content.select('*').each(function(element) {
      element.toggleClassName('render');
    });
    this.afterShow();
  },
  
  hide: function() {
    this.element.hide();
    if (this.draggable) {
      this.draggable.destroy();
      this.draggable = null;
    }
  },
  
  toggle: function() {
    if (this.element.visible()) {
      this.hide();
    } else {
      this.show();
    }
  },
  
  focus: function() {
    var form = this.element.down('form');
    if (form) {
      var elements = form.getElements().reject(function(e) { return e.type == 'hidden' });
      var element = elements[0] || form.down('button');
      if (element) element.focus();
    }
  },
  
  beforeShow: function() {
    this.centerWindowInView();
  },
  
  afterShow: function() {
    if (this.element.down('.popup.draggable')) this.makeDraggable();
    this.focus();
  },

  centerWindowInView: function() {
    var offsets = document.viewport.getScrollOffsets();
    this.element.setStyle({
      left: parseInt(offsets.left + (document.viewport.getWidth() - this.element.getWidth()) / 2) + 'px',
      top: parseInt(offsets.top + (document.viewport.getHeight() - this.element.getHeight()) / 2.2) + 'px'
    });
  }
});

Popup.Window = Class.create(Popup.AbstractWindow, {
  initialize: function($super, element, options) {
    $super(options);
    element.remove();
    this.content.update(element);
    element.show();
  }
});

Popup.AjaxWindow = Class.create(Popup.AbstractWindow, {
  initialize: function($super, url, options) {
    $super();
    options = Object.extend({reload: true}, options);
    this.url = url;
    this.reload = options.reload;
  },
  
  show: function($super) {
    if (!this.loaded || this.reload) {
      new Ajax.Updater(this.content, this.url, {asynchronous: false, method: "get", evalScripts: true, onComplete: $super});
      this.loaded = true;
    } else {
      $super();
    }
  }
});

Popup.Alert = Class.create(Popup.AbstractWindow, {
  initialize: function($super, message, options) {
    $super();
    this.options = Object.extend({
      title: 'Alert'
    }, (options || {}));
    this.message = message;
  },
  
  beforeShow: function($super) {
    var titleBar = $h3({'class':'title'}, this.options.title);
    var buttonBar = $div({'class':'buttons'});
    var popup = $div({'class':'popup'},
      titleBar,
      $div({'class':'popup_content'},
        $p(this.message),
        buttonBar
      )
    );
    this.content.insert(popup);
    
    this.okButton = $a({href:'#ok'}, 'OK');
    this.okButton.observe('click', this.close.bindAsEventListener(this));
    buttonBar.insert(this.okButton);
    
    if (this.options.beforeShow) this.options.beforeShow(this);
    $super();
  },
  
  close: function(event) {
    this.element.remove();
    event.stop();
  }
});
Popup.alert = function(message, options) {
  new Popup.Alert(message, options).show();
};

// Element extensions
Element.addMethods({
  closePopup: function(element) {
    $(element).up('table.popup_window').hide();
    return $(element);
  }
});

Event.addBehavior.reassignAfterAjax = true;
Event.addBehavior({
  'a.popup, button.popup': Popup.TriggerBehavior()
});

var InputHintBehavior = Behavior.create({
  initialize: function() {
    this.hint = this.element.getAttribute('alt')
    if (this.element.getAttribute('type') == 'password') this.passwordField = true;
    this.originalColor = this.element.getStyle('color');
    if (this.originalColor.blank()) this.originalColor = '#000';
    
    this.onblur();
    if (!this.passwordField) this.element.up('form').observe('submit', this.onfocus.bind(this));
  },
  
  onblur: function() {
    if (this.element.getValue().blank()) {
      if (this.passwordField) this.element.setAttribute('type', 'text');
      this.element.setValue(this.hint);
      this.element.setStyle('font-style:italic; color:#999');
    }
  },
  
  onfocus: function() {
    if (this.element.getValue() == this.hint) {
      if (this.passwordField) this.element.setAttribute('type', 'password');
      this.element.setValue('');
      this.element.setStyle('font-style:inherit; color:' + this.originalColor)
    }
  }
});

if (Prototype.Browser.IE) {
  Event.addBehavior({
     'input[type="text"][alt], textarea[alt]': InputHintBehavior()
  });
} else {
  Event.addBehavior({
    'input[alt], textarea[alt]': InputHintBehavior()
  });
}


var LegalToggle = Class.create({
  initialize: function() {
    this.toggling = false;
    
    var legaleseHandle = $('legalese_handle'),
        humanHandle = $('human_handle');
    legaleseHandle.observe('click', this.onclick.curry('legalese', 'human'));
    humanHandle.observe('click', this.onclick.curry('human', 'legalese'));
    
    legaleseHandle.down('img').setRotate(90);
    
    [legaleseHandle, humanHandle].invoke('setStyle', 'cursor:pointer');
  },
  
  onclick: function(sectionOneName, sectionTwoName, event) {
    var sectionOne = $(sectionOneName + '_version'),
        sectionOneHandle = $(sectionOneName + '_handle').down('img'),
        sectionTwo = $(sectionTwoName + '_version'),
        sectionTwoHandle = $(sectionTwoName + '_handle').down('img');
    if (!this.toggling) {
      if (sectionOne.visible()) {
        if (!window.toggling) window.toggling = true;
        
        sectionOneHandle.rotate({from:90, to:0});
        sectionOne.slideUp({onComplete: function() {
          sectionTwo.slideDown({onComplete: function() {
            this.toggling = false;
          }});
          sectionTwoHandle.rotate({from:0, to:90});
        }});
      } else {
        if (!this.toggling) window.toggling = true;
        
        sectionOneHandle.rotate({from:0, to:90});
        sectionOne.slideDown({onComplete: function() {
          sectionTwo.slideUp({onComplete: function() {
            this.toggling = false
          }});
          sectionTwoHandle.rotate({from:90, to:0});
        }});
      }
    }
  }
});

Event.addBehavior({
  '#legal': function() { new LegalToggle() }
});

// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

Element.addMethods({
  fadeIn: function(element) {
    if (element.visible()) return;
    
    element.setOriginal('opacity', element.getStyle('opacity'));
    
    var effect = new Fx.Style(element, 'opacity', {
      onComplete: function() {
        element.setStyle('display:block; opacity:' + element.originalOpacity);
      },
      duration: 100
    });
    effect.set(0);
    effect.custom(0, element.originalOpacity);
  },
  
  fadeOut: function(element) {
    if (!element.visible()) return;
    
    element.setOriginal('opacity', element.getStyle('opacity'));
    
    var effect = new Fx.Style(element, 'opacity', {
      onComplete: function() {
        element.setStyle('display:none; opacity:' + element.originalOpacity);
      },
      duration: 100
    });
    effect.set(element.originalOpacity);
    effect.custom(element.originalOpacity, 0);
  },
  
  // Rotate elements, in the format of element.rotate({from: angle1, to: angle2})
  rotate: function(element, options) {
    var from = options.from || 0,
        to = options.to;
    
    var interval = setInterval(function() {
      if (from < to) {
        from += 3
        if (from >= to) clearInterval(interval);
      } else {
        from -= 3
        if (from <= to) clearInterval(interval);
      }
      element.setStyle('-moz-transform:rotate(' + from + 'deg); -webkit-transform:rotate(' + from + 'deg)');
    }, 10)
  },
  
  setRotate: function(element, angle) {
    element.setStyle('-moz-transform:rotate(' + angle + 'deg); -webkit-transform:rotate(' + angle + 'deg)');
  },
  
  // Show elements in a smooth fashion
  slideDown: function(element, options) {
    if (element.visible()) return;
    
    options = options || {};
    element.setOriginal('height', element.getHeight());
    element.setOriginal('overflow', element.getStyle('overflow'));
    
    var effect = new Fx.Style(element, 'height', {
      duration: 500 + (element.originalHeight / 6),
      onStart: function() {
        element.setStyle('height:0px; display:block; overflow:hidden');
        if (options.onStart) options.onStart();
      },
      onComplete: function() {
        element.setStyle('overflow:' + element.originalOverflow);
        if (options.onComplete) options.onComplete();
      }
    });
    effect.set(0);
    effect.custom(0, element.originalHeight);
  },
  
  slideToggle: function(element, options) {
    if (element.visible()) element.slideUp(options);
    else element.slideDown(options);
  },
  
  // Hide elements in a smooth fashion
  slideUp: function(element, options) {
    if (!element.visible()) return;
    
    options = options || {};
    element.setOriginal('height', element.getHeight());
    element.setOriginal('overflow', element.getStyle('overflow'));
    
    var effect = new Fx.Style(element, 'height', {
      duration: 500 + (element.originalHeight / 6),
      onStart: function() {
        element.setStyle('overflow:hidden');
        if (options.onStart) options.onStart();
      },
      onComplete: function() {
        element.setStyle('display:none; overflow:' + element.originalOverflow);
        if (options.onComplete) options.onComplete();
      }
    });
    effect.set(element.originalHeight);
    effect.custom(element.originalHeight, 0);
  },
  
  setOriginal: function(element, property, value) {
    if (!element['original' + property.capitalize()]) element['original' + property.capitalize()] = value;
  }
})

var Timezone = {
  set : function() {
    var date = new Date();
    var timezone = "timezone=" + -date.getTimezoneOffset() * 60;
    date.setTime(date.getTime() + (1000*24*60*60*1000));
    var expires = "; expires=" + date.toGMTString();
    document.cookie = timezone + expires + "; path=/";
  }
}
Event.observe(document, 'dom:loaded', function() { Timezone.set() });