﻿// Month Tab Calendar Event Renderer
var MonthEventsRenderer = function(){this.ctor.apply(this, arguments);};Object.SetProperties(MonthEventsRenderer.prototype, 
{
   ctor:function()
   {
     var args = Object.ToArray(arguments);
     this.EManager = args[0];
   },
   
   EManager:null,
   HeaderHeight:15,
   /*
   DayDiff:function(d1, d2){
     var m1 = new Date(d1<d2?d1:d2);
     var m2 = new Date(d1<d2?d2:d1);
     return (m2-m1)/86400000; //1000*60*60*24=86400000
   },
   */
   
   // Calculate Distance 
   DDayDiff:function(d1, d2){
     var m1 = new Date(d1<d2?d1:d2);
     var m2 = new Date(d1<d2?d2:d1);
     m1.setHours(0,0,0,0);
     m2.setHours(0,0,0,0);
     return (m2-m1)/86400000; //1000*60*60*24=86400000
   },
   
   // Calculate Label Width 
   RDayDiff:function(d1, d2){
     
     var m1 = new Date(d1<d2?d1:d2);
     var m2 = new Date(d1<d2?d2:d1);
     var aaa = new Date();
     
     m1.setHours(0,0,0,0);
     if((m2-m1)%86400000==0)return ((m2-m1)/86400000);
     
     m2.setHours(0,0,0,0);
     m2.setDate(m2.getDate()+1);
     return (m2-m1)/86400000; //1000*60*60*24=86400000
   },
   
   Render:function(body, list)
   {
      body.innerHTML = "";
      
      // Styles and Labels 
      var styles = this.EManager.Styles.Month;
      var labels = this.EManager.Labels.Month;
      var settings = this.EManager.Settings.Month;
      
      // Date calculation
      var sWeek = 0;
      var date = this.EManager.ShowingDate;
     
      var sDate = new Date(date); sDate.setDate(1); sDate.setDate(1-(7+sDate.getDay()-sWeek)%7); sDate.setHours(0,0,0,0);
      var eDate = new Date(date); eDate.setMonth(eDate.getMonth()+1); eDate.setDate(0); eDate.setDate(eDate.getDate()+((sWeek+7)-(eDate.getDay()+1))%7);eDate.setHours(0,0,0,0);
      var cDate = new Date(sDate);
      var totalDay = (eDate-sDate)/(1000*60*60*24)+1;
      var totalWeek = totalDay/7; 
      
      // Render Day Month Year Container
      var div0 = Object.NewTagInto(body, "div", {style:{textAlign:'right', height:'8%', width:'100%'}});
            
      // Render Month Select
      var mSel = Object.NewTagInto(div0, "select");
      for(var i=0; i<12; i++){
        Object.NewTagInto(mSel, "option", {innerHTML:labels.MonthLabels[i], value:i+1, selected:date.getMonth()==i});
      }
      
      // Render Year Select
      var ySel = Object.NewTagInto(div0, "select");
      var cMonth = new Date(date); cMonth.setFullYear(cMonth.getFullYear()-10);
      for(var i=0; i<20; i++){
        Object.NewTagInto(ySel, "option", {innerHTML:cMonth.getFullYear(), value:cMonth.getFullYear(), selected:date.getFullYear()==cMonth.getFullYear()});          
        cMonth.setFullYear(cMonth.getFullYear()+1);
      }
      
      var btnGo = Object.NewTagInto(div0, "input", {type:'button', value:'Go'});
      
      var MonthYearChange = function(div, list, mSel, ySel, manager)
      {
         var date = new Date(mSel.value+"/1/"+ySel.value);
         var sDate = new Date(date); sDate.setDate(1); sDate.setDate(1-(7+sDate.getDay()-sWeek)%7);
         var eDate = new Date(date); eDate.setMonth(eDate.getMonth()+1); eDate.setDate(0); eDate.setDate(eDate.getDate()+((sWeek+7)-(eDate.getDay()+1))%7);      
      
         manager.GetEventList(sDate, eDate, function(body, date, manager, list){
           manager.ShowingDate = date;
           var mer = new MonthEventsRenderer(manager);
           mer.Render(body, list);
         }.Bind(this, body, date, manager));
      }

      // Render Month and Year Change Action
      Object.SetProperties(btnGo, {onclick:MonthYearChange.Bind(this, body, list, mSel, ySel, this.EManager)});      
      
      
      // Create Calendar Division
      var div = Object.NewTagInto(body, "div", {style:{position:'relative', display:'block', width:'100%', height:'92%', overflow:'hidden', border:'1px solid gray', padding:'0px 0px 0px 0px'}});;

      // Maximum event show in day
      var maxShow = settings.MaxEventRow;
      maxShow = (totalWeek>5)?maxShow-1:maxShow;
            
      var weekHeight = 15;
      var rWidth = div.clientWidth%7;
      var rHeight = (div.clientHeight-weekHeight)%7;
      var dWidth = Math.round((div.clientWidth-rWidth)/7);
      var divHeight = Math.round((div.clientHeight-weekHeight-rHeight)/totalWeek);
      
      var headHeight = 14;
      var footHeight = 15;
      var bodyHeight = divHeight-footHeight-headHeight;
      
      
      Object.SetProperties(div.style, {width:(div.clientWidth-rWidth)+'px', height:(div.clientHeight-rHeight)+'px'})
      
      // Render Calender Week Header       
      var headerDiv = Object.NewTagInto(div, "div", {style:{position:'relative', top:'0px', left:'0px', display:'block', width:7*dWidth+'px', height:weekHeight+'px', styleFloat:'left', cssFloat:'left', margin:'0px 0px 0px 0px'}});
      var headerUL = Object.NewTagInto(headerDiv, "div", {style:{position:'relative', left:'0px', listStyle:'none', padding:'0px', margin:'0px 0px 0px 0px', height:weekHeight+'px', styleFloat:'left', cssFloat:'left'}});
      for(var i=0; i<7; i++)
      {
        var li = Object.NewTagInto(headerUL, "li", {innerHTML:labels.DayLabels[(i+sWeek)%7]});
        Object.SetProperties(li, styles.GetStyle("Header"), {style:{width:(dWidth-1)+'px', height:weekHeight+'px', styleFloat:'left', cssFloat:'left'}});
      }
      
      // Calculate Event Label Position 
      var listPos = new Array();
      list.Foreach(function(item){listPos.push({Event:item, Pos:{Top:1, Div:1}});})
      
      var max=0, md=1;
      while(max<md)
      {
        max++;
        var rItem = null;
        for(var i=0; i<listPos.length; i++)
        {
           var cItem = listPos[i];
           rItem = (rItem==null && cItem.Pos.Top==max?cItem:rItem);
           if(rItem!=null && cItem.Pos.Top==max && cItem!=rItem)
           {
             var t1 = new Date(rItem.Event.From); t1.setHours(0,0,0,0);
             var t2 = new Date(rItem.Event.To); t2.setHours(0,0,0,0); t2.setDate(t2.getDate()+1);
             
             var t4 = new Date(cItem.Event.From); t4.setHours(0,0,0,0); //t4.setDate(t4.getDate()+1);
             
             if(new Range(t1, t2, true, false).IsCover(t4))
             //if(new Range(rItem.Event.From, rItem.Event.To, true, false).IsCover(cItem.Event.From))
             {
               cItem.Pos.Top++;
               md=cItem.Pos.Top+1;
             }
             else
               rItem = cItem;
           }           
        } 
      }
      listPos.Foreach(function(item){item.Pos.Div=md;});
      
      
      
      // Render Calander 
      var showedEventList = new Array();
      var listDayEvent = {};
      
      var manager = this.EManager;
      
      for(var i=0; i<totalWeek; i++)
      {
        
        var weekOfMonth = i;
        
        var month = Object.NewTagInto(div, "div", {style:{position:'relative', top:'0px', left:((dWidth*7)*i*-1)+'px', display:'block', width:(totalDay*dWidth)+'px', height:divHeight+'px', styleFloat:'left', cssFloat:'left', margin:'0px 0px 0px 0px'}}); 
        var ul = Object.NewTagInto(month, "ul", {style:{position:'relative', left:'0px', listStyle:'none', padding:'0px', margin:'0px 0px 0px 0px', height:divHeight+'px', styleFloat:'left', cssFloat:'left'}}); 
        
        var ssDate = new Date(sDate); ssDate.setDate(ssDate.getDate()+(weekOfMonth*7));ssDate.setHours(0,0,0,0);
        var eeDate = new Date(sDate); eeDate.setDate(eeDate.getDate()+((weekOfMonth+1)*7));eeDate.setHours(0,0,0,0);          
        var weekRange = new Range(ssDate, eeDate, true, true);
        
        for(var cdate=new Date(sDate); cdate<=eDate; cdate.setDate(cdate.getDate()+1))
        {  
           var dayDiv = Object.NewTagInto(ul, "li", {style:{left:'0px', top:'0px', fontSize:'10px', borderTop:'1px gray solid', borderLeft:'1px gray solid', width:(dWidth-1)+'px', height:divHeight+'px', styleFloat:'left', cssFloat:'left'}});
           
           if(!weekRange.IsCover(cdate))continue;
           
           //Style setting 
           var styMonth = date.getMonth()==cdate.getMonth()?styles.GetStyle("ThisMonth"):styles.GetStyle("OtherMonth");
           var styDay = cdate.getDay()==0||cdate.getDay()==6?styles.GetStyle("WeekDay"):styles.GetStyle("WorkingDay");
           var styMonthAndDay = (styMonth.className && styDay.className)?{className:styMonth.className +" "+ styDay.className}:Object.Union(styMonth, styDay);
           
           Object.SetProperties(dayDiv, styMonthAndDay, cdate.toDateString()==new Date().toDateString()?styles.GetStyle("Today"):{}, {});
              
           var dateLink=Object.NewTagInto(dayDiv, "a", {style:{styleFloat:'right', cssFloat:'right', clear:'both', height:headHeight+"px", fontSize:(headHeight-2)+'px'}, href:'javascript:void(0)', innerHTML:(cdate.getDate().toString().length==1?"":"")+cdate.getDate(), onclick:function(date, manager){
             manager.ShowingDate = date;
             var from = new Date(date);
             var to = new Date(date); to.setDate(to.getDate()+1);to.setMilliseconds(to.getMilliseconds()-1);
             manager.ListShow = "day";
             manager.EventCalendar.TabContainer.FocusToTab(manager.EventCalendar.TabContainer.TabExist("Day")?"Day":"List");
           }.Bind({}, new Date(cdate), this.EManager)});
           
           var dayStart = cdate;
           var dayEnd = new Date(dayStart); dayEnd.setHours(24,0,0,0);
           var rangeDay = new Range(dayStart, dayEnd, true, false);

           var matces = listPos.GetMatches(function(item){             
             var r1 = new Range(item.Event.From, item.Event.To, true, false);
             return !r1.IsBefore(rangeDay) && !r1.IsAfter(rangeDay);            
           });
                      
           if(matces.length>maxShow)
           {
             var divMore = Object.NewTagInto(dayDiv, "div", {style:{position:'relative', clear:'both', cssFloat:'right', styleFloat:'right', height:footHeight+'px', width:''}});
             var lblMore = Object.NewTagInto(divMore, "a", {href:'javascript:void(0)', innerHTML:labels.More, onclick:function(date, manager){
               manager.ShowingDate = date;
               manager.ListShow = "day";
               manager.EventCalendar.TabContainer.FocusToTab(manager.EventCalendar.TabContainer.TabExist("Day")?"Day":"List");
             }.Bind({}, new Date(cdate), this.EManager),
             style:{}});
             
             divMore.style.top = (divHeight-(divMore.clientHeight+dateLink.clientHeight)) + "px"
             
             new MoreEventRenderer(divMore, labels.EventOnDay, matces, styles.GetStyle("MoreToolTip"));             
           }
        }
        
        var parent = this;
        var lblEventArrowWidth = 13;

        listPos.Foreach(function(ep){   
          
          var ffDate = new Date(sDate); ffDate.setDate(ffDate.getDate()-1);
          
          var evt = ep.Event;
          var pos = ep.Pos;
          //var from = new Date(evt.From);
          var from = new Date(evt.From<ffDate?ffDate:evt.From);
          var to = new Date(evt.To);
          var eventRange = new Range(from, to, true, true);
              
          if(pos.Top > maxShow) return; // return if the current event is greater than the maximum show
          
          var lblMargin = 2;
          var lblHeight = (Math.round(bodyHeight/maxShow))-lblMargin;
          var lblFontSize = lblHeight-(lblMargin)-2;
          
          var totalMonthCover = parent.RDayDiff(to, from); totalMonthCover = (totalMonthCover>32?50:totalMonthCover);
          var lblWidth = Math.round( totalMonthCover * dWidth )-1;
          
          //var lblWidth = Math.round( parent.RDayDiff(to, from) * dWidth )-1;
          var lblLeft  = Math.round( (sDate<from?1:-1) * (parent.DDayDiff(sDate, from)) * dWidth );
          var lblTop = headHeight + ((pos.Top-1)*(lblHeight+lblMargin)) ;
          var lblTextIndent = lblEventArrowWidth;
          
          // Border left and right of the label
          lblLeft+=lblMargin;
          lblWidth-=lblMargin*2;
          
          var lblEvt = Object.NewTagInto(month, "span", styles.GetStyle("GeneralLabel"), {style:{display:pos.Top>maxShow?'none':'block', filter:"alpha(opacity=75)", opacity:'0.75', top:lblTop+'px', border:'1px solid gray', cursor:'pointer', left:lblLeft+'px', width:lblWidth+'px', height:(lblHeight-3)+'px', position:'absolute', overflow:'hidden', textAlign:'left', styleFloat:'left', cssFloat:'left', clear:'left'}});

          new EventDetailRenderer(evt, manager, lblEvt)
          
          // Highlight Event Label
          if(!listDayEvent[evt.ID])listDayEvent[evt.ID] = new Array();
          listDayEvent[evt.ID].push(lblEvt);
            
          Object.SetProperties(lblEvt, {
            onmouseover:function(list, sty){
              list.Foreach(function(lbl){
                Object.SetProperties(lbl, sty);
                Object.SetProperties(lbl.style, {filter:"alpha(opacity=100)", opacity:'1.00'});
              });
            }.Bind(lblEvt, listDayEvent[evt.ID], styles.GetStyle("FocusLabel")),
            onmouseout:function(list, sty){
              list.Foreach(function(lbl){
                Object.SetProperties(lbl, sty);
                Object.SetProperties(lbl.style, {filter:"alpha(opacity=75)", opacity:'0.75'});
              });
            }.Bind(lblEvt, listDayEvent[evt.ID], styles.GetStyle("GeneralLabel"))             
          });
          // Highlight Event Label
          
          
          //left and right arrow
          var lblEvtLeftArrow = null;
          var lblEvtRightArrow = null;
          
          var lblEvtTextleft = lblEventArrowWidth-lblMargin;
          
          var rangeL = new Range(from, to, false, true);
          if(rangeL.IsStepIn(weekRange) || rangeL.IsCover(weekRange))
          {
             var lblEvtArrow_left = parent.RDayDiff(rangeL.Min, weekRange.Min) * dWidth;
             lblEvtLeftArrow = Object.NewTagInto(lblEvt, "span", {innerHTML:"&#9668;", style:{color:'black', fontSize:'10px', fontWeight:'bolder', position:'relative', left:lblEvtArrow_left+'px', width:lblEventArrowWidth+"px", overflow:'hidden'}});
            
             lblEvtTextleft -= lblEventArrowWidth-lblMargin-(parent.RDayDiff(rangeL.Min, weekRange.Min) * dWidth);
          }

          var rangeR = new Range(from, to, true, false);          
          if(rangeR.IsStepOut(weekRange) || rangeR.IsCover(weekRange))
          {
             var lblEvtArrow_right = (parent.RDayDiff(rangeR.Min, weekRange.Max) * dWidth) + (lblEvtLeftArrow==null?0:lblMargin) - (lblEventArrowWidth*(lblEvtLeftArrow==null?1:2));
             lblEvtRightArrow = Object.NewTagInto(lblEvt, "span", {innerHTML:"&#9658;", style:{color:'black', fontSize:'10px', fontWeight:'bolder', position:'relative', left:lblEvtArrow_right+"px", width:lblEventArrowWidth+"px", overflow:'hidden'}});
             
             lblEvtTextleft -= lblEventArrowWidth-lblMargin;
          }              
          

          //  middle Text          
          //lblEvtTextleft += ((rangeL.IsCover(weekRange) || rangeL.IsStepIn(weekRange)) ? parent.RDayDiff(rangeL.Min, weekRange.Min) * dWidth : 0 ); 
          Object.NewTagInto(lblEvt, "span", {innerHTML:(evt.URL==""?"":"<a href='" + evt.URL + "' target='_blank'><img src='" + settings.UrlImage + "' border='0' height='80%'></a> ")  + evt.Title, style:{position:'relative', left:lblEvtTextleft+'px' /*, fontSize:lblFontSize+"px"*/}});
            
          new ToolTipEventRender(lblEvt, evt, styles.GetStyle("EventToolTip"), manager.Labels.Tooltip);
          
          

          
        });

      }  
   }
});
