// usage:
//     <!-- important: redefine mod_cal$show_month, mod_cal$postprocess, mod_cal$filter_events and mod_cal$feed_url below -->
//     <!-- important: include with charset utf-8 -->
//     <script type="text/javascript" charset="utf-8" src="fkis_mod_cal.js"></script>
//     <link rel="stylesheet" type="text/css" href="fkis_mod_cal.css" /> 
//
//     <!-- invoke the calendar as per examples below -->
//     fkis_mod_cal.show('mod_cal','en-gb','week');    // english week view, now ONLY
//     fkis_mod_cal.show('mod_cal','zh-cn','week');    // chinese week view, now ONLY
//     fkis_mod_cal.show('mod_cal','en-gb','month');   // english month view, now
//     fkis_mod_cal.show('mod_cal','zh-cn','month',4); // chinese month view, four months from now
//
// notes:
//     exported as window.fkis_mod_cal

(function(){

  // configurations: options (EDIT)
  var mod_cal$debug_headers = false;
  var mod_cal$feed_cache = true;
 	var current_campus = 0;
  // configuration: json feed (EDIT)
  var mod_cal$feed_url = '/home/eventsdata';
  
  // configuration: redirect to the monthly calendar view (EDIT)
  function mod_cal$show_month(target) {
    var sfx = (fkis_mod_cal.lang=='zh-cn'?'-'+fkis_mod_cal.lang:'');
    window.location = '/admissions'+sfx+'/calendar'+sfx;
     // fkis_mod_cal.show(target,fkis_mod_cal.lang,'month',0); // now
  }

  
  // configuration: add calendar view paging controls and/or post-processing (EDIT)
  function mod_cal$postprocess(cal) {  
    // use jQuery like this if you need to:
    //   var $ = jQuery;
    //
    // click handler should look like:     
    //   $(..).click( function(){fkis_mod_cal.show(cal.target,cal.lang,cal.view,+1);} );
    //
    // use cal.date.month && cal.date.day && cal.date.year to set calendar label, as in:
    //    $('myMonthDiv').innerHTML = mod_cal$trans.month[cal.lang][cal.date.month]; 
    //    $('myYearDiv').innerHTML = cal.date.year;
    //
    if (cal.view=='month') {
      if (cal.lang=='zh-cn') {
        with_class($('mod_cal_widget'),'campuslabel',function(e){
        	var c = mod_cal$trans.campus[cal.lang];
          e.innerHTML = '<p>' +  ' ' + c[alk_get_campus('m')]+ '</p>';
        });
 		  } else {
        with_class($('mod_cal_widget'),'campuslabel',function(e){
        	var c = mod_cal$trans.campus[cal.lang];
          e.innerHTML = '<p>' + ' ' +  c[alk_get_campus('m')] + '</p>';
        });
      }
    } else { // week view
      try {
       if (cal.lang=='zh-cn') {
        with_class($('mod_cal_widget_header'),'campuslabel',function(e){
        	var c = mod_cal$trans.campusweek[cal.lang];
          e.innerHTML = '<p>' +  ' ' + c[alk_get_campus('w')]+ '</p>';
        });
 		  } else {
        with_class($('mod_cal_widget_header'),'campuslabel',function(e){
        	var c = mod_cal$trans.campusweek[cal.lang];
          e.innerHTML = '<p>' + ' ' +  c[alk_get_campus('w')] + '</p>';
        });
      }
      } catch (e) {
      	// ignore missing campuslabel
      }
    }
    
    if (cal.view=='month') {
      if (cal.lang=='zh-cn') {
        with_class($('mod_cal_widget'),'datelabel',function(e){
          e.innerHTML = '<p>' + cal.date.year + ' ' + mod_cal$trans.month[cal.lang][cal.date.month] + '</p>';
        });
      } else {
        with_class($('mod_cal_widget'),'datelabel',function(e){
          e.innerHTML = '<p>' + mod_cal$trans.month[cal.lang][cal.date.month] + ' ' + cal.date.year + '</p>';
        });
      }
    }

    if (cal.view=='week') {    	
     	if (cal.lang=='zh-cn') {
        with_class($('mod_cal_widget'),'datelabel',function(e){
        	e.innerHTML = '<p>' + cal.date_week.getFullYear() + '-' + (cal.date_week.getMonth()+1) + '-' + 
                        cal.date_week.getDate() + '</p>';
        });
      } else {
        with_class($('mod_cal_widget'),'datelabel',function(e){
        	e.innerHTML = '<p>' + mod_cal$trans.month[cal.lang][cal.date_week.getMonth()] + ' ' + 
                        cal.date_week.getDate() + ' ' + cal.date_week.getFullYear() + '</p>';
        });
      }
    }

    with_class($('mod_cal'),'today',function(e){
      e.innerHTML = '<div class="pagefold"></div>' + e.innerHTML ;
    });
    /*
    $(cal.target).innerHTML +=
       '<a class="header flat bright" '+
         'onclick="javascript:fkis_mod_cal.show(\''+cal.target+'\',\''+cal.lang+'\',\'month\',-1)">'+mod_cal$trans['btn_prev'][cal.lang]+'</a>' +
       '<a class="header flat bright" '+
         'onclick="javascript:fkis_mod_cal.show(\''+cal.target+'\',\''+cal.lang+'\',\'month\',+1)">'+mod_cal$trans['btn_next'][cal.lang]+'</a>' +
       '<br>';
   */
  }

  // configuration: drop events that don't apply given current context (EDIT)
  // 0:all, 1-5:specific, 6:intl, 7:local
  function mod_cal$filter_events(cal,evts) {
    var e = new Array();
    // adjusting campus name array indices to match event campus ids
    var campus = (cal.view=='week'?alk_get_campus('w')*1+1:alk_get_campus('m')*1+6);
    for (var i=0; i<evts.length; i++) {
      // language filter (unicode trick)
      if (!evts[i].title || cal.lang!=evts[i].ext.lang) continue;
      // campus
      if (evts[i].campusType!=campus && evts[i].campusType!=0) continue;
      // event type: ignore. 
      e.push(evts[i]);
    }
    return e;
  }

  // configuration: translations
  var mod_cal$trans = {
    'default':    'en-gb',
    valid:      { 'en-gb':true, 
                  'zh-cn':true },
    now:        { 'en-gb' : 'TODAY',
                  'zh-cn' : '今' },
    dateday:    { 'en-gb' : '',
                  'zh-cn' : '日' },
    datemonth:  { 'en-gb' : '',
                  'zh-cn' : '月' },
    day:        { 'en-gb' : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
                  'zh-cn' : ['周日','周一','周二','周三','周四','周五','周六'] },
    month:      { 'en-gb' : ['January','February','March','April','May','June','July','August','September','October','November','December'],
                  'zh-cn' : ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'] },
    'btn_prev': { 'en-gb' : 'PREV', 
                  'zh-cn' : '上' },
    'btn_next': { 'en-gb' : 'NEXT', 
                  'zh-cn' : '下' },
    campus:     { 'en-gb':  [ 'International', 'Local'],
    							'zh-cn':  [ '国际', '中国']},
    campusweek: { 'en-gb':  [ 'Dongfang', 'Longyang','Hongqiao','Yaohua','OCT'],
    							'zh-cn':    ['东方园','龙阳园','虹桥园','耀华园','华侨园']},
    school:     { 'en-gb':  [ 'International School Year Calendar','Local School Year Calendar'],
    						  'zh-cn':  ['国际班年历','中国班年历']}
 }; 
  // caching and sync
  var mod_cal$feed_data = null;    // fetch events once only
  var mod_cal$feed_request = null; // unnec?

  // utils
  function _(e)               { if (document.getElementById) return document.getElementById(e); else return document.all[e]; }
  function $(e)               { if (typeof e == 'string') return _(e); else return e; }
  function def(o,v,d)         { if (!o) o={}; if (!o[v]) o[v]=d; return o; }
  function snil(s)            { return s?s:''; }
  function dom(ty,c,id,cl,ce) { return '<'+ty+' id="'+snil(id)+'" '+(ce?' onclick="javascript:'+ce+'"':'')+' class="'+snil(cl)+'">'+c+'</'+ty+'>'; };
  function span(c,id,cl,ce)   { return dom('span',c,id,cl,ce); }
  function div(c,id,cl,ce)    { return dom('div',c,id,cl,ce); }

  // apply a function to any el or child element that is a member of css classname
  function with_class(el,classname,fn) { 
      if ((el=$(el)).className && el.className.indexOf(classname)>=0) fn(el);          
      for (var i=0;el.childNodes && i<el.childNodes.length;i++) with_class(el.childNodes[i],classname,fn);
  }

  // language detection hacks
  function detect_lang(deflang) { return (fkis_mod_cal.lang = detect_lang0(deflang)); }
  function detect_lang0(deflang) {
    // zh-cn and en-gb only
    var b = document.getElementsByTagName('body');
    if (b && b.length>0) b=b[0];
    if (b && b.className.toLowerCase().indexOf('zh-cn')>=0) return 'zh-cn';
    if (document.URL.toLowerCase().indexOf('zh-cn')>=0) return 'zh-cn';
    if (deflang) return deflang;
    return 'en-gb';
  }

  
  // returns a rendered calendar and associated data
  function mod_cal(config) {

    var label = '', header = '', calendar = '';
  
    // utils 
    function today(d)        { return now.getFullYear()==t.getFullYear() && now.getMonth()==t.getMonth() && now.getDate()==t.getDate(); }
    
    // validate
    config = def(config,'view','week');
    config = def(config,'lang','en-gb');
    config = def(config,'offset',0);
    if (!mod_cal$trans.valid[config.lang]) config.lang=mod_cal$trans["default"];
    
    // calc calendar start
    var now = new Date();
    var M = now.getMonth() + (config.view=='week'?0:config.offset);
    var D = now.getDate()  + (config.view=='week'?config.offset_week:0);
    var Y = now.getFullYear();
    var day0 = new Date();
    if (config.view!='week') {
      while (M>=12) { M-=12; Y+=1; }
      day0.setUTCFullYear(Y);
      day0.setUTCMonth(M,1);
      day0.setUTCHours(0);
      day0.setUTCMinutes(0);
      day0.setUTCSeconds(0);            
    }



    // headers and labels
    if (config.view!='week') {
      // label
      label += div(''+mod_cal$trans.month[config.lang][day0.getMonth()],'header-month','header label bold ') ;
      label += div(''+day0.getFullYear(),'header-year','header label bold ') + '<br>';
      // header
      for(var i=1;i<8;i++) {
        header += span(div(mod_cal$trans.day[config.lang][i%7],null,'headname'),'header-day-'+(i%7)+' ','header bold '+(i>5?' weekend ':''));
      }
      header += '<br>'
    }
    
    // handle monday start day 
    var wshift = day0.getDay()-1;
    switch (wshift) {
      case -1: wshift = wshift + 7;  break;
      case +0: wshift = 0;  break;
    }
    day0.setDate(day0.getDate()-wshift+config.offset_week);
                
    // build grid
    var t = new Date(day0);
    var wview = (config.view=='week'?'weekview ':'monthview ');
    for(var j=0; j<6; j++) {
      for(var i=0; i<7; i++) {              
        var dayname = (config.view=='week'?mod_cal$trans.day[config.lang][t.getDay()]:'');
        calendar += span(
            span(t.getDate(),'',' daynum ') + span(dayname,'','dayname '),
            'events-'+t.getFullYear()+'-'+(t.getMonth()+1)+'-'+t.getDate(),
            'cell '+(t.getMonth()!=M ? '' : 'curmonth ')+(i>4?'weekend ':'')+(today(t)?'today ':'')+wview,
            (config.view=='week'?'fkis_mod_cal.show_month(\''+config.target+'\')':'null')            
          );
        t.setDate(t.getDate()+1);
      }
      calendar += '<br>'; 
      if (config.view=='week' || t.getMonth()>M || t.getMonth()<M) break;
    }
    var day1=t;
    calendar += '<div class="clear:both;"></div>';
    calendar += '<div style="clear:both;padding:0px;margin:0px;"></div>';
    return {
        range: { start:day0.getTime(), end:day1.getTime() },  // start <= valid_time < end
        view:  config.view,                                   // current view
        lang:  config.lang,                                   // current language
        date_week: day0,                                      // start date of 'this' week
        date:  { month:M, day:day0.getDate(), year:Y },       // current view month/year
        html:  { label:label, header:header, grid:calendar }, // current calendar html              
        config: config
      };
  } // mod_cal
  
  // handle the showing and hiding of popups
  function mod_cal$show_popup(target,id) {
    with_class($(target),'popup',function(e){
        while (e.className.indexOf('show')>=0)  { e.className=e.className.replace('show',''); }
        e.className += ' hide ';
      });
    if (id=$(id)) {
      while (id.className.indexOf('hide')>=0)  { id.className=id.className.replace('hide',''); }
      id.className += ' show ';
    }
  }

  // fetch events (ajax bits)
  function mod_cal$get_events(cal,noajax) {
    function __newxmlreq () {
      var v = [ "MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP" ];
      try { return new XMLHttpRequest(); } catch(e) {};
      for (var i = 0; i < v.length; i++) try { return new ActiveXObject(v[i]); } catch (e) {};  
      throw new Error("XMLHttpRequest not found");
    }          
    function xmlreq (url,pdata,opt_content_type,opt_on_load,opt_on_error) {
      var req = feed_request = __newxmlreq();
      req.open((pdata!=null?"POST":"GET"), url, !noajax);
      if (opt_content_type) {
        try { req.setRequestHeader("Content-Type",opt_content_type); } catch (e) {};
        try { req.overrideMimeType(opt_content_type); } catch (e) {};
      }
      req.onreadystatechange = function () {
        try {
          if (req.readyState==4) {
            if (req.status == 200 && opt_on_load)  opt_on_load(req); 
            if (req.status != 200 && opt_on_error) opt_on_error(req);
          } 
        } catch (e) { if (opt_on_error) opt_on_error(req,e); else throw e; };
      }
      req.send(pdata);
      return req;
    };    
    if (mod_cal$feed_cache && mod_cal$feed_data) {
       mod_cal$render_events(cal,mod_cal$feed_data);
       mod_cal$render_event_list(cal);
    } else {
      feed_request = xmlreq(mod_cal$feed_url,null,null,function(r){ 
         if (r==feed_request) {
             mod_cal$render_events(cal,mod_cal$feed_data=r.responseText);
             mod_cal$render_event_list(cal);
         }
       },function(r){});
    }
  }

   function mod_cal$render_event_list(cal) {
   	function pad2(s) { s=s+''; if (s.length<2) s = pad2('0'+s); return s; }
   	function format_event(evt) {  
   		var d0 = pad2(evt.ext.start.getDate()); 
   		var m0 = mod_cal$trans.month[cal.lang][evt.ext.start.getMonth()];
   		var d1 = pad2(evt.ext.end.getDate()); 
   		var m1 = mod_cal$trans.month[cal.lang][evt.ext.end.getMonth()];
   		var M = mod_cal$trans.datemonth[cal.lang];
   		var start = ''; var end = ''; 
   		if (cal.lang=='en-gb') {    			
   			start = m0 + ' ' + d0;
   			if (d0!=d1 || m0!=m1) end = ' - ' + m1 + ' ' + d1;
   		} else {
        var m0 = pad2(evt.ext.start.getMonth()+1)+M;
        var m1 = pad2(evt.ext.end.getMonth()+1)+M;
   			start = m0 + d0 + mod_cal$trans.dateday[cal.lang];
   			if (d0!=d1 || m0!=m1) end = ' ～ ' + m1 + d1 + mod_cal$trans.dateday[cal.lang];   			
   		}
   		return '<div id="EventView"><li id="CalDate">' + start + end + '</li><li id="CalTitle">' + evt.title + '</li></div>';
   	}
  	if (cal.view=='month') {
  		var evts = cal.event_data.filtered;
  		var text = "";
      for (var i=0; i<evts.length; i++) {
      	text += format_event(evts[i]);
      }
      $('event_list').innerHTML = text;
			var school = mod_cal$trans.school[cal.lang][alk_get_campus('m')*1];
  	  $('schoolType').innerHTML = school;	
  	}
  }

  function detect_language(s,opt_date) {
  	var c = 0;
  	if (s && s.length>0) {
    	for (var i=0;i<s.length;i++) if (s.charCodeAt(i)>127) c++;    	
    	if (c/s.length>0.2) return 'zh-cn';
  	}
 	  return 'en-gb';
  }

  // re-interpret and filter events
  function mod_cal$process_events(cal,event_text) {
    var evts = eval(event_text).sort(function(a,b){return a.start-b.start;});
    for (var i=0; i<evts.length; i++) {
      evts[i].ext = {
        // convert from unix time
        start: new Date(1000*evts[i].start),
        end:   new Date(1000*evts[i].end),
        // detect language type
        lang:  detect_language(evts[i].title,new Date(1000*evts[i].end))
      };
    }
    cal.event_data = fkis_mod_cal.event_data = { text:event_text, original:evts, filtered:evts=mod_cal$filter_events(cal,evts) };
    return evts;
  }
  
  // render events
  function mod_cal$render_events(cal,event_text) {        
    evts = mod_cal$process_events(cal,event_text);
    for (var i=0;i<evts.length;i++) {
      var e = evts[i];
      var s = e.start;
      if ( (evts[i].ext.start.getTime()>=cal.range.start && evts[i].ext.end.getTime()<cal.range.end) ||
          (evts[i].ext.end.getTime()>=cal.range.start)) {
        var id = 'events-' + e.ext.start.getFullYear() + '-' + (e.ext.start.getMonth()+1) + '-' + e.ext.start.getDate() ;
        if ($(id)) {
          var eid = id + '-' + e.id;
          var click = (cal.view=='week'?'javascript:fkis_mod_cal.show_month(\''+cal.target+'\')':'');
          $(id).innerHTML +=                 
            '<div '+
               'onmouseout="javascript:fkis_mod_cal.show_popup(\''+cal.target+'\')" '+
               'onmouseover="javascript:fkis_mod_cal.show_popup(\''+cal.target+'\',\'popup-'+eid+'\')" '+
               'onclick="'+click+'" '+
               'class="event '+cal.view+'view etype'+(e.important==1?4:e.eventType)+'">' + 
              '<div id="popup-'+eid+'" class="popup '+cal.view+'view hide">'+
                  '<div class="arrow"></div>'+
                  e.title+
               '</div>'+
            '</div>';
        }
        var t = new Date(e.ext.start);
        while (t.getTime()<e.ext.end.getTime()) {
          var id = 'events-' + t.getFullYear() + '-' + (t.getMonth()+1) + '-' + t.getDate();
          if ($(id)) $(id).className += ' etype'+e.eventType;
          t.setDate(t.getDate()+1);
        }
      }
    }
  }

  // render week/month calendar
  function mod_cal$show(target,lang,view,move,noajax) {
  	fkis_mod_cal.target = target;
    fkis_mod_cal.lang   = lang?lang:detect_lang();
    fkis_mod_cal.view   = view;              
    if (view=="month")
      fkis_mod_cal.offset = (!move?0:fkis_mod_cal.offset+(Math.abs(move)>1?0:move)); 
    else 
      fkis_mod_cal.offset_week = (!move?0:fkis_mod_cal.offset_week+move);       
    var cal = null;
    if (view=='week') {
      cal = mod_cal(fkis_mod_cal);
      // cal = mod_cal({ view:'week', offset:0, lang:lang, target:target });
      cal.target = target;
      $(target).innerHTML = cal.html.grid;
    } else {            
      cal = mod_cal(fkis_mod_cal);
      cal.target = target;
      $(target).innerHTML = (mod_cal$debug_headers?cal.html.label + cal.html.header :'') + cal.html.grid;
    }
    mod_cal$postprocess(cal);          
    mod_cal$get_events(cal,noajax);
    return cal;
  }

  // export 
  window.fkis_mod_cal = { 
    view:'month', 
    offset:0, 
    offset_week:0,
    lang:'zh-cn', 
    show:mod_cal$show, 
    show_popup:mod_cal$show_popup, 
    show_month:mod_cal$show_month,
    trans: mod_cal$trans,
    event_data: null,
    fn: {
      $:$,
      with_class:with_class,
      detect_lang:detect_lang
    }
  }; 

})();
