/* Javascript code for FBM_Form Class */

var FBM_Form = Class.create();
FBM_Form.prototype = {
  
  initialize: function(initOptions) {
    
    this.options = Object.extend({
      lang:                'de',
      defaultLang:         'en',
      knownLangs:          ['en', 'de'],
      
      formContainer:       'content_main',   // container, mostly div, containig form with id of 'formId'
      formId:              'fbm_form',
      labelIdSuffix:       '_l',             // 'field' value from 'statusCodes' + 'labelIdSuffix' is id of form element label 
      highlightClass:      'fbm_red',        // to highlight with 'highlightClass' if data from the field is invalid
      
      STR:                 {                 // list of localized strings
                             close:         {en: 'close', de: 'schliessen'}
                           }, 
      
      generalErrorCode:    1000,             // code - service not available
      successStatusCode:   0,                // code - everything went fine
      statusCodes:         {},               // user own status codes
      statusRootNode:      'FbmForm',        // root node in response status XML
      showResponseHTML:    true,             // if response is a HTML, not our status XML, show it or not
      
      dimmOverlayClass:    'dimm_window',    // overlay_ prefix will be added, 'dialog' class was default
      dimmOverlayOpacity:  0.6,
      dialogWidth:         680,
      dialogHeight:        600,
      emailFormat:         /^[a-z\'0-9]+([\._\-][a-z\'0-9]+)*@[a-z0-9]+([\.\-][a-z0-9]+)*\.[a-z]{2,5}$/i,
      
      endScreenTemplate: '\
<div class="section_headline">#{section_headline}</div> \
<h3 class="#{headline_class}">#{headline}</h3> \
<div id="#{form_id}"> \
  <br/> \
  <p>#{text}</p> \
  <br/> \
  <a class="btn_right" href="javascript:void(0);" onclick="var fbmF=new FBM_Form; fbmF.closeDialog();"><img src="/img/btn_close_#{lang}.png" alt="#{close_str}" title="#{close_str}" /></a> \
</div> \
'
    }, initOptions || {});
    
    
    // status code data
    // key is statusCode, value is an associative array, where key is lang codes as keys, message text as value;
    // for each status odese there is an extra key 'field' possible containing id of form element corresponding
    // with this status (mostly error) code
    this.statusCodes = Object.extend({
        1000: {
                 de:    'Dieser Service ist vorübergehend nicht verfügbar.<br/>Bitte versuchen Sie es in Kürze noch einmal. Vielen Dank.',
                 en:    'This service is temporary not available.<br/>Please try again a little later. Thank you.'
              }
    }, this.options.statusCodes || {}); 
    
    
    // check current and default lang
    if (this.options.knownLangs.indexOf(this.options.defaultLang) == -1)
      this.options.defaultLang = this.options.knownLangs[0];  // unknown default lang - take the first known
    
    if (this.options.knownLangs.indexOf(this.options.lang) == -1)
      this.options.lang = this.options.defaultLang;
  },
  
  openDialog: function(url) {
    // dialogbox is defined in fbmUtils
    dialogbox(url, this.options.dialogWidth, this.options.dialogHeight);
  },
  
  closeDialog: function() {
    if (typeof window.profileWin != 'undefined') {
      var win = window.profileWin;
      Windows.close(win.element.id);
    } else if (typeof window.parent.profileWin != 'undefined') {
      var win = window.parent.profileWin;
      window.parent.Windows.close(win.element.id);
    } else {
      window.close();
    }
  },
  
  // validate the form and return error data if sth is wrong
  checkForm: function() {
     var errMsgs = [], errFields = [];
     
     // validate user data and return array with err codes
     var errCodes = this.getErrorCodes();
     
     // get error messages and fields for err codes
     var that = this;
     var errData = errCodes.inject([], function(array, code) {
       var v = that.getStatusMsg(code);
       if (v) array.push(v);
       return array;
     });
     
     errData.each( function(err) {
       if (typeof err.msg != 'undefined' && err.msg != '')
         errMsgs.push(err.msg);
       
       if (typeof err.field != 'undefined')
         errFields.push(err.field);
     });
     
     return (errMsgs.length) ? {msg: errMsgs, field: errFields} : {};
  },
  
  // check if email matches email regex
  checkEmail: function(email) {
    return email.match(this.options.emailFormat);
  },
  
  submitForm: function() {
    // first local data validation
    var error = this.checkForm();
    if (typeof error.msg != 'undefined') {
       this.showErrorMsg(error);
       return;
    } 
    
    var form = $(this.options.formId);
    if (form) {
      // send form as AJAX request
      var req = Form.Methods.request(form, {
        onLoading:   this.showWaitScreen.bind(this, true),
        onSuccess:   this.feedback.bind(this),
        onFailure:   this.feedback.bind(this),
        onException: this.feedback.bind(this)
      });
    }
  },
  
  resetForm: function() {
    var form = $(this.options.formId);
    if (form)
      Form.reset(form);
  },
  
  // process AJAX response
  feedback: function(xhr) {
    var statusCode = this.options.generalErrorCode;
    var statusMsg  = '';
    var lang = this.options.lang;
    
    // parse response XML and get values: statusCode, statusMsg and its lang
    if (xhr.responseXML && xhr.responseXML.childNodes) {
      // find root node
      var rootNode = null;
      for (var i=0; i < xhr.responseXML.childNodes.length; i++) {
        if (xhr.responseXML.childNodes[i].nodeName == this.options.statusRootNode) {
          rootNode = xhr.responseXML.childNodes[i];
          break;
        }
      }
      
      if (rootNode && rootNode.childNodes) {
        // process status values
        var values = rootNode.childNodes;
        for (i=0; i < values.length; i++) {
          if (values[i].nodeType == 1) { // element node
            switch (values[i].nodeName) {
              case 'statusCode':
                statusCode = values[i].firstChild.nodeValue;
                statusCode = statusCode.strip().gsub(/<br\s*\/?>/i, ''); // strip whitespaces and new lines
                var s = parseInt(statusCode); 
                if (!isNaN(s)) statusCode = s;
                break;
              
              case 'statusMsg': 
                statusMsg = values[i].firstChild.nodeValue;
                lang = values[i].getAttribute('lang');
                break;
            }
          }
        }
      }
    }
    
    // get message using status code first
    var msg = this.getStatusMsg(statusCode, null, statusMsg);
    if (!msg) msg = statusMsg; // use text from XML
    
    // enable window
    this.showWaitScreen(false);
    
    if (this.options.showResponseHTML && xhr.responseText && 
      !(xhr.responseXML && xhr.responseXML.childNodes && xhr.responseXML.childNodes.length)) {
        if (Prototype.Browser.IE) {
          // IE throws 'permission denied' error _AFTER_ replacing html document with 'document.open...' method,
          // so workaround - additionaly we have to use html entities, because document encoding get missing
          newHTML = xhr.responseText.strip().htmlentities(4);  // must be global!
          document.location.replace('javascript: newHTML');
          //var bodyRe = new RegExp('<body[^>]*>([\\S\\s]*?)<\/body>', 'im');
          //document.body.innerHTML = (xhr.responseText.match(bodyRe) || ['', ''])[1];
        } else {
          document.open('text/html', 'replace');
          document.write(xhr.responseText);
          document.close();
        }
    } else if ([this.options.successStatusCode, this.options.generalErrorCode].flatten().indexOf(statusCode) == -1) {
      // some application error occurred - show it on a form screen
      this.showErrorMsg(msg);
    } else if (statusCode == this.options.generalErrorCode) {
      // general error - service not available
      this.showEndScreen(msg, true);
    } else {
      // successful submission
      this.showEndScreen(msg);
    }
  },
  
  // get localized message text and optionally field ids for passed status code
  getStatusMsg: function(code, lang, statusMsg) {
    // unknown status code
    if (typeof this.statusCodes[code] == 'undefined') return null;
    
    // status message
    if (typeof lang == 'undefined' || !lang)
      lang = this.options.lang;
    
    var msg = this.statusCodes[code][lang];
    // if no msg text in the current lang, get for default lang
    if (typeof msg == 'undefined' || msg == '')
      msg = this.statusCodes[code][this.options.defaultLang];
    var res = {msg: msg || statusMsg};
    
    // add associated field with this status code
    if (typeof this.statusCodes[code]['field'] != 'undefined')
      res['field'] = this.statusCodes[code]['field'];
    
    return res;
  },
  
  // while AJAX request show some wait-screnn - here dimm the form window
  showWaitScreen: function(waitOn) {
    if (waitOn) {
      // add an dimmed div to keep catching mouse event over iframes
      WindowUtilities.disableScreen(this.options.dimmOverlayClass, 'dimmWindow', this.options.dimmOverlayOpacity);
    } else {
      // remove temporary div over iframes
      WindowUtilities.enableScreen('dimmWindow');
    }
  },
  
  // show error message on a form screen, highlighting labels of wrong fields
  showErrorMsg: function(error) {
    if (typeof error.msg == 'undefined') {
        error.msg = error;
    }
    
    // get whole error text
    if (Object.isArray(error.msg)) 
      error.msg = error.msg.join('<br/>');
    
    if (error.msg == '') return;
    
    // show error message, creating error box if needed
    var fel = $('feedbackbox');
    if (!fel) {
      fel = new Element('h3', {id: 'feedbackbox', className: this.options.highlightClass});
      Element.insert($(this.options.formContainer), {top:fel});
    }
    Element.update(fel, error.msg);
    
    // if error field is present too, hightlight its label
    if (typeof error.field != 'undefined') {
       // remove highlight from all labels first
       Element.select(this.options.formId, 'label').invoke('removeClassName', this.options.highlightClass);
       
       if (!Object.isArray(error.field))
         error.field = [error.field];
       
       // highlight label of error field(s)
       var that = this;
       error.field.each( function(f) {
         Element.addClassName(f + that.options.labelIdSuffix, that.options.highlightClass);
       });
       
       // set focus on the first error element
       var errEl = $(error.field[0]);
       if (errEl && errEl.focus)
         errEl.focus();
    } 
    
    window.scrollTo(0,0);
  },
  
  // show result message on an end screen
  showEndScreen: function(message, err) {
    if (typeof message.msg == 'undefined') {
      message.msg = message;
    }
    
    // get whole message text
    if (Object.isArray(message.msg)) 
      message.msg = message.msg.join('<br/>');
    
    // remove form
    var cont = $(this.options.formContainer);
    if (cont) {
      var templ = new Template(this.options.endScreenTemplate);
      var tplData = this.getEndScreenData(message, err);
      
      cont.childElements().invoke('remove');
      cont.insert(templ.evaluate(tplData));
    }
  },
  
  // return localized text for the current lang
  _str: function(text) {
     if (typeof this.options.STR[text] == 'undefined') return text;
     
     if (typeof this.options.STR[text][this.options.lang] != 'undefined')
       return this.options.STR[text][this.options.lang];
     
     if (this.options.STR[text][this.options.defaultLang] != 'undefined')
       return this.options.STR[text][this.options.defaultLang];
     
     return text;
  },
  
// methods that probably needs override in a child class //
  
  // validate form before send and return array with error codes
  getErrorCodes: function() {
     return [];
  },
  
  // get data to display on the end screen
  getEndScreenData: function(message, err) {
    return {
      section_headline:  '',
      headline_class:    (err) ? this.options.highlightClass : '',
      headline:          message.msg,
      text:              '',
      form_id:           this.options.formId,
      lang:              this.options.lang,
      close_str:         this._str('close')
    };
  }
};

/* Newsletter Class */
var FBM_Newsletter = Class.create(FBM_Form, {
  
  initialize: function($super, initOptions) {
    var options = Object.extend({
      
      subscribeUrlde:    '/de/unternehmen/presse_pr/newsletter/anmeldung/',  //http://www.buchmesse.de
      subscribeUrlen:    '/en/company/press_pr/newsletter/subscribe/',       //http://www.book-fair.com
      unsunscribeUrlde:  '/de/unternehmen/presse_pr/newsletter/abmeldung/',
      unsunscribeUrlen:  '/en/company/press_pr/newsletter/unsubscribe/',
      formId:            'nl_subscription',
      successStatusCode: [10, 11],
      statusRootNode:    'KajomiNewsletter',        // root node in response status XML
      
      statusCodes:       {
                            10: {                // subscribe OK
                                   de:    '',    // show text from response XML
                                   en:    ''
                                },
                            11: {                // unsubscribe OK
                                   de:    '',
                                   en:    ''
                                },
                            21: {
                                   de:    'Sie haben vergessen Ihren Vornamen anzugeben!',
                                   en:    'You have forgotten to give your first name!',
                                   field: 'fname'
                                },
                            22: {
                                   de:    'Sie haben vergessen Ihren Nachnamen anzugeben!',
                                   en:    'You have forgotten to give your surname!',
                                   field: 'lname'
                                },
                            31: {
                                   de:    'Sie haben vergessen Ihre E-Mail-Adresse anzugeben!',
                                   en:    'You have forgotten to give your e-mail address!',
                                   field: 'email'
                                },
                            32: {
                                   de:    'Die angegebene E-Mail-Adresse ist ungültig!',
                                   en:    'The e-mail address as indicated is invalid!',
                                   field: 'email'
                                },
                            41: {
                                   de:    'Sie sind bereits als Abonnent registriert!',
                                   en:    'You are already registered as a subscriber!',
                                   field: 'email'
                                },
                            51: {
                                   de:    'Diese E-Mail-adresse steht auf der Blacklist',
                                   en:    'The e-mail address as indicated is on the blacklist!',
                                   field: 'email'
                                },
                            85: {
                                   de:    'Bitte Einverständnis ankreuzen.',
                                   en:    'Please confirm your assent.',
                                   field: 'assent'
                                },
                          1000: {
                                   de:    'Dieser Service ist vorübergehend nicht verfügbar.<br/>Bitte versuchen Sie es in Kürze noch einmal. Vielen Dank. (newsletter@book-fair.com)',
                                   en:    'This service is temporary not available.<br/>Please try again a little later. Thank you. (newsletter@book-fair.com)'
                                }
                         }
    
    }, initOptions || {});
    
    // call parent constructor
    $super(options);
  },
  
  openDialogSub: function() {
    this.openDialog(this.options['subscribeUrl' + this.options.lang]);
  },
  
  openDialogUnsub: function() {
    this.openDialog(this.options['unsunscribeUrl' + this.options.lang]);
  },
  
  // validate form before send and return array with error codes
  getErrorCodes: function() {
    var errCodes = [];
    
    if ($('email')) {
      if ($F('email') == '')
        errCodes.push('31');
      else if (!this.checkEmail($F('email')))
        errCodes.push('32');
    }
    
    if ($('assent') && !$F('assent')) {
      errCodes.push('85');
    }
    
    return errCodes;
  }
});

/* Email2Friend Class */
var FBM_Email2Friend = Class.create(FBM_Form, {
  
  initialize: function($super, initOptions) {
    
    var options = Object.extend({
      
      sendEmailUrlde:    '/de/email2friend/index.html',
      sendEmailUrlen:    '/en/email2friend/index.html',
      sendEmailUrlro:    '/ro/email2friend/index.html',
      sendEmailUrlru:    '/ru/email2friend/index.html',
      
      knownLangs:        ['en', 'de', 'ro', 'ru'],
      STR:               {                 // list of localized strings
                             close:         {en: 'close', de: 'schließen', ro: 'închideti', ru: 'закрыть'}
                         }, 
      
      formId:            'email2friend',
      statusRootNode:    'Email2Friend',        // root node in response status XML
      dialogHeight:      602,
      
      statusCodes:       {
                            0:  {
                                   de:    'Vielen Dank. Die Nachricht wurde erfolgreich versendet.',
                                   en:    'Thank you. The message was successfully sent.',
                                   ro:    'Mulţumim. Mesajul Dvs. a fost trimis.',
                                   ru:    'Большее спасибо. Ваше сообщение было успешно отправлено.'
                                },
                            21: {
                                   de:    'Sie haben vergessen Empfänger E-Mail-Adresse anzugeben.',
                                   en:    'You have forgotten to give recipient e-mail address.',
                                   ro:    'Aţi uitat să menţionaţi adresa destinatarului.',
                                   ru:    'Вы забыли указать электронный адрес получателя.',
                                   field: 'recipient_email'
                                },
                            22: {
                                   de:    'Die angegebene Empfänger E-Mail-Adresse ist ungültig.',
                                   en:    'The recipient e-mail address as indicated is invalid.',
                                   ro:    'Adresa destinatarului nu este valabilă.',
                                   ru:    'Указанный вами адрес получателя не действителен.',
                                   field: 'recipient_email'
                                },
                            31: {
                                   de:    'Sie haben vergessen Absender Namen anzugeben.',
                                   en:    'You have forgotten to give sender name.',
                                   ro:    'Aţi uitat sa menţionaţi numele expeditorului.',
                                   ru:    'Вы забыли указать имя отправителя.',
                                   field: 'sender_name'
                                },
                            41: {
                                   de:    'Sie haben vergessen Absender E-Mail-Adresse anzugeben.',
                                   en:    'You have forgotten to give sender e-mail address.',
                                   ro:    'Aţi uitat sa menţionaţi adresa adresa expeditorului.',
                                   ru:    'Вы забыли указать электронный адрес отправителя.',
                                   field: 'sender_email'
                                },
                            42: {
                                   de:    'Absender E-Mail-Adresse ist ungültig.',
                                   en:    'Sender e-mail address as indicated is invalid.',
                                   ro:    'Adresa expeditorului nu este valabilă.',
                                   ru:    'Электронный адрес отправителя не действителен.',
                                   field: 'sender_email'
                                },
                            51: {
                                   de:    'Bitte geben Sie den Verifizierungscode ein.',
                                   en:    'Please put the verify code.',
                                   ro:    'Vă rugăm introduceţi codul verificat.',
                                   ru:    'Пожалуйста введите код верификации.', 
                                   field: 'verify_code'
                                },
                            52: {
                                   de:    'Der Verifizierungscode stimmt nicht überein.',
                                   en:    'The verify code does not match.',
                                   ro:    'Codul verificat nu este corect.',
                                   ru:    'код верификации не верен', 
                                   field: 'verify_code'
                                },
                          1000: {
                                   de:    'Dieser Service ist vorübergehend nicht verfügbar.<br/>Bitte versuchen Sie es in Kürze noch einmal. Vielen Dank.',
                                   en:    'This service is temporary not available.<br/>Please try again a little later. Thank you.',
                                   ro:    'Acest serviciu este temporar inaccesibil.<br/>Vă rugăm încercaţi mai târziu. Mulţumim.',
                                   ru:    'Данный сервис временно не доступен.<br/>Пожалуйста повторите позже. Большое спасибо.' 
                                }
                         }
    
    }, initOptions || {});
    
    // call parent constructor
    $super(options);
  },
  
  // fill article fields with data
  init: function() {
    // get parent document where article data is stored
    var p = (parent === self) ? null : parent;
    
    var queryString = window.location.search.toQueryParams();
    
    // get article data: url, page title and teaser
    this.articleUrl    = (p) ? (p.location.protocol + '//' + p.location.hostname + p.location.pathname) : queryString.url;
    this.articleTitle  = (p) ? p.document.title : queryString.title;
    this.articleTeaser = '';
    
    if (p) {
      // get teaser from parent - first h3 in the content_main div
      var contentMain = p.document.getElementById('content_main');
      if (contentMain) {
        var h3s = [];
        if (typeof document.importNode != 'undefined') {
          // FF3 does not allow direct access to external nodes; IE6+7, FF2 and Safari2 do
          var localContentMain = document.importNode(contentMain, true);
          h3s = Element.select(localContentMain, 'h3');
        } else {
          h3s = Element.select(contentMain, 'h3');
        }
        if (h3s.length)
          this.articleTeaser = h3s[0].innerHTML;
      }
    } else {
      // get from query sting
      this.articleTeaser = queryString.teaser;
    }
    
    // copy article data in the email form
    var error = false;
    if (typeof this.articleUrl != 'undefined' && this.articleUrl != '') {
      $('article_url').setValue(this.articleUrl);
      
      if (typeof this.articleTitle != 'undefined' && this.articleTitle != '') {
        $('article_title').setValue(this.articleTitle);
      } else {
        error = true;
      }
      
      // set own lang value
      $('lang').setValue(this.options.lang);
      
      // teaser is optional
      if (typeof this.articleTeaser != 'undefined' && this.articleTeaser != '')
        $('article_teaser').setValue(this.articleTeaser);
    } else {
       error = true;
    }
    
    // general error - service not available
    if (error)
      this.showEndScreen(this.getStatusMsg(this.options.generalErrorCode), true);
  },
  
  openDialogSendEmail: function() {
    this.openDialog(this.options['sendEmailUrl' + this.options.lang]);
  },
  
  // validate form before send and return array with error codes
  getErrorCodes: function() {
    var errCodes = [];
    
    if ($('recipient_email')) {
      if ($F('recipient_email') == '')
        errCodes.push('21');
      else if (!this.checkEmail($F('recipient_email')))
        errCodes.push('22');
    }
    
    if ($('sender_name') && $F('sender_name') == '') {
      errCodes.push('31');
    }
    
    if ($('sender_email')) {
      if ($F('sender_email') == '')
        errCodes.push('41');
      else if (!this.checkEmail($F('sender_email')))
        errCodes.push('42');
    }
    
    // verify code
    if ($('verify_code') && $F('verify_code') == '') {
      errCodes.push('51');
    }
    
    return errCodes;
  }
  
});
