
/**
 * Open a modal/confirm box for the given link.
 * 
 * Usage:
 *
 * Iframe
 * <a href='http://www.google.com' class='modal' rel='iframe'>Google</a>
 *
 * Ajax
 * <a href='ajax/ajax.jsp' class='modal'>AJAX</a>
 *
 *
 * Confirm
 * <a href='do/action.jsp' class='modal confirm' title="Are you sure ?">Confirm Link</a>
 * <input value='Confirm Button' class='modal confirm' title="Are you sure ?" />
 */

// ---------------------------------------
//  MODAL
// ---------------------------------------

'JCMS.window.Modal'.namespace({

  OVERLAY_OPACITY: 0.60,
  FADE_DURATION: 0.20,

  init: function(){
    var t0 = new Date().getTime();
    
    Util.observeClass('modal', JCMS.window.Modal._show);
    Util.observeClass('popin', JCMS.window.Modal._popinCB);
    Util.observeClass('popin-close', JCMS.window.Popin.afterCloseCB); // Should be an other function calling popin.close();
    
    var t1 = new Date().getTime();
    JcmsLogger.info('Modal', 'Init Modal', ' in '+(t1-t0)+' ms');
  },
  
  relocate: function(event){
    if (JCMS.window.Modal.current){
      JCMS.window.Modal.current.position();
    }
  },
  
  /**
   * Close the current Modal window
   * @return boolean to be used in onclick="" 
   * (eg true => The modal is not closed, false => The modal has been closed)
   */
  close: function(confirmValue){ 
    var modal = JCMS.window.Modal.current;
    if (modal){
      modal._confirm = confirmValue;
      return !modal.close();
    }
    return true;
  },
  
  /**
   * Create and Display a Modal Window for the alert message
   * @param msg the alert message
   */
  alert: function(msg){
    var modal = JCMS.window.Modal._showAlert(function(){}, 'alert', msg);
    JCMS.window.Modal._openModal(modal);
  },
  
  /**
   * Create and Display a Modal Window for the confirm message
   * @param msg the alert message
   * @param func the callback function
   * @param usage optional parameter that will define class/jsp used (default is confirm)
   */
  confirm: function(msg, func, usage){
    var modal = JCMS.window.Modal._showAlert(func, usage || 'confirm', msg);
    JCMS.window.Modal._openModal(modal);
  },
  
  /**
   * Create and Display a Modal Window for the prompt message
   * @param msg the alert message
   * @param func the callback function
   * @param defvalue the default value
   */
  prompt: function(msg, func, defvalue){
    var modal = JCMS.window.Modal._showAlert(function(value){ 
      if (value != undefined){ func(value); }
	  }, 'prompt', msg,  defvalue);
	  JCMS.window.Modal._openModal(modal);
  },
  
  /**
   * Create and Display a Modal Window for the given JSP
   * @param jsp the JSP
   * @param callback the callback function
   * @param parameters the parameters
   */
  showJSP: function(jsp, callback, parameters){
    var modal = JCMS.window.Modal._createModal(jsp, callback, parameters);
    JCMS.window.Modal._openModal(modal);
  },
  
  /**
   * Create and Display a Popin with the given content and title
   * @param content the content
   * @param title the title
   * @param options the options (className, ...)
   */
  popin: function(content, title, options){
    var options = options || {};
    options.content = content;
    JCMS.window.Modal._popin(false, title, options);
    return false;
  },
  
  // ----------------------------------------
  //  Private
  // ----------------------------------------
  
    
  /**
   * Create and Display a Modal Window for the current event
   * @param event the document click event
   * @param elm the A/BUTTON/INPUT element being clicked
   * @param classname the matching classname
   */
  _show: function(event, elm, classname){
    Event.stop(event);
    var modal;
    if (elm.hasClassName('warning')) {
      modal = JCMS.window.Modal._showConfirm(elm,'warning');
    }
    else if (elm.hasClassName('confirm')) {
      modal = JCMS.window.Modal._showConfirm(elm);
    }
    else if (elm.hasClassName('prompt')) {
      modal = JCMS.window.Modal._showPrompt(elm);
    }
    else {
      modal = JCMS.window.Modal._showModal(elm);
    }
    
    // Display the modal
    JCMS.window.Modal._openModal(modal, event);
  },
  
  _popinCB: function(event, trigger, classname){
    Event.stop(event);
    
    var title = trigger.readAttribute('title');
    var href  = trigger.href;
    var url   = href + ((href.indexOf('?') == -1) ? '?rd=' : '&rd=') + Math.random();
    var timeout = trigger.fastClassMatch(/popin-timeout-(\d+)/,1);
    
    JCMS.window.Modal._popin(url,title, {
      draggable: trigger.hasClassName('popin-drag'), 
      override:  trigger.hasClassName('popin-override'),
      className: trigger.className,
      timeout:   timeout ? parseInt(timeout) : false
    });
  },
  
  _popin: function(url, title, option){
  
    if (option && option.override){
      var last = JCMS.window.Popin._popins.last();
      if (last){ last.close(); }
    }
  
    var popin = new JCMS.window.Popin(url, title, option);
    popin.open();
    
    return popin;
  },
  
  _openModal: function(modal, event){
    if(!modal){ return; }
    if (event){ Event.stop(event); }
    
    JCMS.window.Modal.current = modal;
    JCMS.window.Modal.current.open(event);
    $(document.body).addClassName('modal-displayed');
  },
  
  _showModal: function(tag){
    
    // Case 0: I am in a Modal ?
    var inModal = tag.fastUp(['DIV'],'modal',false,10);
    if (inModal){
      JcmsLogger.warn('Modal','Cannont open a Modal in a Modal');
      return false;
    }
    
    // Case 1 : IFRAME requested through "rel" attribute
    if (tag.rel && tag.rel == 'iframe'){
      var window_header  = new Element('div', { className: 'iframe-modal-header'  });
      var window_title   = new Element('div', { className: 'iframe-modal-title'   });
      var window_close   = new Element('div', { className: 'iframe-modal-close'   });
      var window_content = new Element('div', { className: 'iframe-modal-content' });

      var options = JCMS.window.Modal._buildModalOption('iframe-modal', null, {
          iframe: true,
          closeOnClick: window_close,
          insertRemoteContentAt: window_content,
          width: function(){ return document.viewport.getWidth()-100; },
          height: function(){ return document.viewport.getHeight()-100; }
      });
      var modal = new Control.Modal(tag, options);

      modal.container.insert(window_content);
      modal.container.insert(window_header);
      window_header.insert(window_title);
      window_header.insert(window_close);
      window_title.update(tag.readAttribute('title') || tag.href);
      
      return modal;
    } 

    // Case 2 : IMAGES
    if (tag.hasClassName('close-modal') || (tag.href && tag.href.match(new RegExp('(jpg|jpeg|gif|png|bmp)([?][^?]+)*$','img')))) {
      // If we are in a iframe, do not open the modal as the iframe might
      // be too small for the modal to be visible, instead use a popup 
      if (Util.isInIFrame()) {
        Popup.popupWindow(tag.href, tag.readAttribute('title') || tag.href, 640, 480);
        return null; // correctly handled later by _openModal
      }
      var options = JCMS.window.Modal._buildModalOption('image-modal', null, {
        closeOnClick: true
      });
      var modal = new Control.Modal(tag, options);
      
      var close_btn  = new Element('IMG', { className: 'modal-close-btn', src: 's.gif'  });
      modal.container.insert(close_btn);
      
      return modal;
    }
    
    // Default : simple modal creation with default options
    var options = JCMS.window.Modal._buildModalOption('def-modal');
    var modal = new Control.Modal(tag, options);
    return modal;
  },
  
  _showConfirm: function(tag,usage){
    return JCMS.window.Modal._showAlert(function(confirm){
      if (!confirm)    { return; }
      
      // Handle onclick: do not work because of bubbling effect
      // if (tag.onclick) {
      //   if (!tag.onclick(confirm)){
      //     return;
      //   }
      // }
      
      // Hand Href also if onlick return true
      if (tag.href)  { document.location = tag.href; }
      
      // Handle button/input with actions
      if (tag.form){
        simpleSubmitForm(window,tag.form,tag.name); 
      }
      
    },usage || 'confirm', tag.title);
  },
  
  _showPrompt: function(tag){
    return JCMS.window.Modal._showAlert(function(value){
      if (!value){ return; }
      if (tag.href) {
        document.location = getUrlWithUpdatedParam(tag.href, 'value', value);
      }
    },'prompt', tag.title);
  },
  
  _showAlert: function(callback, usage, msg, defValue){
    var jsp = 'jcore/modal/'+usage+'.jsp';
    var parameters = { msg: msg, defValue: defValue };
    var classes = usage;
    return JCMS.window.Modal._createModal(jsp, callback, parameters, classes);
  },
  
  _createModal: function(jsp, callback, parameters, classes){
    // Always create a Window because there is no reference to tag
    if (!parameters && jsp.indexOf('?')>0){
      var qs  = jsp.substring(jsp.indexOf('?')+1);
      jsp = jsp.substring(0,jsp.indexOf('?'));
      parameters = qs.toQueryParams();
    }
    
    var modal = new Control.Modal(
      JcmsJsContext.getContextPath()+ "/" + jsp,
      JCMS.window.Modal._buildModalOption(classes, callback, { parameters:parameters })
    );
    return modal;
  },
  
  _buildModalOption: function(classes, callback, options) {
    var defaultOptions = {
      fade: false,
      fadeDuration:   JCMS.window.Modal.FADE_DURATION,
      overlayOpacity: JCMS.window.Modal.OVERLAY_OPACITY,
      className: 'modal '+ (classes || ''),
      height: null,
      position: 'center',
      closeOnClick: false,
      iframeshim: true,
      afterOpen: JCMS.window.Modal._initFocus,
      afterClose: function(){
        $(document.body).removeClassName('modal-displayed');
        
        var modal = JCMS.window.Modal.current;
        if(!modal){ return; } // Prevent timming/dual modal errors
        
        // Retrieve confirm value from modal params
        var confirmValue = modal._confirm;
        
        document.fire('refresh:before',{ wrapper: modal.container.identify() });
        
        JCMS.window.Modal._disposeModal(modal);
        
        // Invoke callback
        if (callback) { callback.delay(0.1, confirmValue); };  // Fix IE6/IE7 Bug: delay code that are too slow in click event scope.
      }
    };
    
    var finalOptions = Object.extend(defaultOptions, options || {});
    return finalOptions;
  },
  
  _initFocus: function(){
    if (!this.container){ return; }
    
    var func = function(){
      
      // Force refresh
      document.fire('refresh:before',{ wrapper: this.container.identify() });
      document.fire('refresh:after' ,{ wrapper: this.container.identify() });
    
      // Focus first .focus
      var focusElm = this.container.down('.focus');
      if (focusElm && focusElm.focus){
        InputUtil.focus(focusElm);
        return; 
      }
    
      // Focus first element
      var form = this.container.down('FORM');
      if (!form){ return; }
      var first = form.findFirstElement();
      if (!first){ return; }
      InputUtil.focus(first);
    }.bind(this);
    
    func.defer();
  },
  
  _disposeModal: function(modal){
    if (modal.container.parentNode){ // make sure we remove the div container (livepipe only do this if the original link is not in the DOM)
      modal.destroy();
    }
    if (modal.container.parentNode){
      modal.container.remove(); 
    }
  }
});

// ---------------------------------------
//  POPIN
// ---------------------------------------

JCMS.window.Popin = Class.create(Control.Window,{
  initialize: function($super, url, title, options) {
  
    var pheader  = new Element('div', { className: 'popin-header'   });
    var ptitle   = new Element('div', { className: 'popin-title'    });
    var pclose   = new Element('div', { className: 'popin-close-btn'});
    var pcontent = new Element('div', { className: 'popin-content'  });
        
    var defaultOptions = {
      width: JcmsJsContext.isIE ? 350 : null, // fix buggy automatic width in IE
      position: [
        JCMS.window.Popin.popinX.bind(this),
        JCMS.window.Popin.popinY.bind(this)
      ],
      className:             'popin-window',
      closeOnClick:          pclose,
      draggable:             false,
      fade:                  true,
      iframeshim:            false,
      insertRemoteContentAt: pcontent,
      afterOpen:  JCMS.window.Popin.afterOpenCB.bind(this),
      afterClose: JCMS.window.Popin.afterCloseCB.bind(this),
      method: 'get'
    };
    
    if (options.draggable){
      options.draggable = pheader;
    }
    
    $super(url, Object.extend(defaultOptions, options || {}));
    
    this.container.insert(pheader);
    this.container.insert(pcontent);
    pheader.insert(ptitle);
    pheader.insert(pclose);
    ptitle.update(title || '&nbsp;');
    
    // Inline content
    if (options.content){
      pcontent.update(options.content);
    }
    
    // Store Popin
    JCMS.window.Popin._popins.push(this);
  }
});

Object.extend(JCMS.window.Popin,{
  
  NW: 1,
  SW: 2,
  NE: 3,
  SE: 4,
  
  _popins: $A([]),
  _anchor: 2,
  
  relocate: function(){
    JCMS.window.Popin._popins.invoke('position');
    
    // Kludge relocate of latest autocomplete
    if (!Ajax.Autochooser){ return; }
    Ajax.Autochooser.relocate.delay(0.5);
  },
  
  afterOpenCB: function(){
    if (this.options.callback){
      this.options.callback(this);
    } 

    if (this.options.timeout){
      this.close.bind(this).delay(this.options.timeout);
    }
    JCMS.window.Popin.relocate.bind(this);
  },
  
  afterCloseCB: function(event, trigger, classname){
    var popin = this;
    if (trigger){
      var wrapper = trigger.fastUp(false,'popin-window');
      popin = JCMS.window.Popin._popins.find(function(pin){ return pin.container == wrapper });
    }
    if (!popin){ return; }
    if (event){ Event.stop(event); }
    
    popin.close();
    
    var pos  = JCMS.window.Popin._popins.indexOf(popin);
    JCMS.window.Popin._popins.splice(pos,1);
    JCMS.window.Modal._disposeModal(popin);
    JCMS.window.Popin.relocate();
  },
  
  popinX: function(){
    if (this.options.draggable && this._setupX){ return Element.positionedOffset(this.container).left; }
    var anchor = JCMS.window.Popin._anchor;
    this._setupX = true;
    return (anchor == 1 || anchor == 2) ? 20 : (document.viewport.getDimensions().width - 20 - this.container.getWidth() + document.viewport.getScrollOffsets().left);
  },
  
  popinY: function(){
    
    if (this.options.draggable && this._setupY){ return Element.positionedOffset(this.container).top; }
    var anchor = JCMS.window.Popin._anchor;
    var pos  = JCMS.window.Popin._popins.indexOf(this);
    var posY = (anchor == 1 || anchor == 3) ? 0 :document.viewport.getDimensions().height ;
    var posH = 0;
    
    var prev = false;
    for (; pos>0 && !prev ; pos--){ 
      var p = JCMS.window.Popin._popins[pos-1];
      prev = p.options.draggable ? false : p; 
    }
    
    if (prev){
      posY = prev.container.positionedOffset().top;
      posH = prev.container.getHeight();
    }
    this._setupY = true;
    
    var scrolly = + document.viewport.getScrollOffsets().top;
    
    return (anchor == 1 || anchor == 3) ?  (posY + posH + 20) : (posY - this.container.getHeight() - 20 + scrolly); 
  }
});


// ---------------------------------------
//  EVENTS 
// ---------------------------------------

Event.observe(window,  'load',   function(){ JCMS.window.Modal.init.defer(); });
Event.observe(window,  'resize', JCMS.window.Popin.relocate);
Event.observe(window,  'scroll', JCMS.window.Popin.relocate);
Event.observe(document,'refresh:after', JCMS.window.Modal.relocate);
Event.observe(document,'refresh:lazy',  JCMS.window.Modal.relocate);




