/*

  epg_week.js -- EPGデータから、今日から一週間分の番組表を編集して表示する。

  使い方:

  week.html:
    <div>
      <script language="javascript" src="epg_week.js"></script>
    <div id="week_12ch">
      <script language="javascript">week_program("12ch","epg.json","week_12ch",5,7);</script>
    </div>
    <div id="week_207ch">
      <script language="javascript">week_program("207ch","epg.json","week_207ch",5,7);</script>
    </div>
    </div>

    week_program(id,url,writeToId,dayStartTime,maxDays);

      id              // 名前空間を分離するためのHTML内でユニークな文字列
      url_of_epg_json // EPGデータ(epg.json)の URL
      writeToId       // 書き込む先の id
      dayStartTime    // 番組表上の、一日の始まりの時刻 5=5:00
      maxDays         // 読み込む最大日数


  $Id$

*/

if(typeof(g) == 'undefined'){ var g=new Array(); }; // グローバル

function epg_week(spc){

  // 時間帯毎の時間と日付部分の背景色
  spc.hour_bg_color=new Array("#66ccff","#66ccff","#66ccff","#66ccff","#66ccff","#66ccff","#66ccff"
                              ,"#FFCC99","#FFCC99","#FFCC99","#FFCC99","#FFCC99","#FFCC99"
                              ,"#9900CC","#9900CC","#9900CC","#9900CC","#9900CC","#9900CC"
                              ,"#9900CC","#9900CC","#9900CC","#9900CC","#9900CC");

  // 時間帯毎の時間と日付部分の背景色
  spc.hour_bg_color=new Array("#66ccff","#66ccff","#66ccff","#66ccff","#66ccff","#66ccff","#66ccff"
                           ,"#FFCC99","#FFCC99","#FFCC99","#FFCC99","#FFCC99","#FFCC99"
                           ,"#9900CC","#9900CC","#9900CC","#9900CC","#9900CC","#9900CC"
                           ,"#9900CC","#9900CC","#9900CC","#9900CC","#9900CC");

  // 時間帯毎の時間と日付の文字色
  spc.hour_color=new Array("#000000","#000000","#000000","#000000","#000000","#000000","#000000"
                        ,"#000000","#000000","#000000","#000000","#000000","#000000"
                        ,"#ffffff","#ffffff","#ffffff","#ffffff","#ffffff","#ffffff"
                        ,"#ffffff","#ffffff","#ffffff","#ffffff","#ffffff");

  // 一番上の日付部分の色を曜日ごとに変えられます。
  spc.wday_color=new Array("#ffcc66","#00cc99","#00cc99","#00cc99","#00cc99","#00cc99","#ccffff");

  // 番組内容の部分も曜日ごとに色を変えられますが、0分に隙間ができてしまいます。
  spc.wday_p_color=new Array("#ffffff","#ffffff","#ffffff","#ffffff","#ffffff","#ffffff","#ffffff");

  spc.programs=eval(spc.req.responseText);
  show_program_table(spc);


}

function makeRequest(){
//
// HTTP Request を返す
//

  var http_request=false;

  if (window.XMLHttpRequest) { // Mozilla, Safari,...
    http_request = new XMLHttpRequest();
    if (http_request.overrideMimeType) {
        //http_request.overrideMimeType('text/xml');
        // See note below about this line
    }
  }else if (window.ActiveXObject){ // IE
    try {
      http_request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        http_request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {}
    }
  }
  if (!http_request) {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
  }
  return http_request;

}

//
// 一週間分を配列に再編集する
//
function make_table_of_program(spc){

  now=new Date();
  now.setTime(now.getTime()-spc.dayStartTime*60*60*1000);
  today=new Date(now.getFullYear(),now.getMonth(),now.getDate());

  var wtable=new Array()
  for(i=spc.dayStartTime;i<24+spc.dayStartTime;i++){
    wtable[i]=new Array();
    for(j=0;j<spc.maxDays;j++){
      wtable[i][j]=new Array();
    }
  }

  for(pi in spc.programs){
    prog=spc.programs[pi]
    program_day=new Date(Math.floor(prog.date/10000)
                        ,(Math.floor(prog.date/100)%100)-1
                        ,prog.date%100
                        ,Math.floor(prog.start/10000)
                        ,Math.floor(prog.start/100)%100
                        ,prog.start%100);
    program_day.setTime(program_day.getTime()-spc.dayStartTime*60*60*1000);
    program_day=new Date(program_day.getFullYear()
                        ,program_day.getMonth()
                        ,program_day.getDate());
    iday=Math.floor((program_day.getTime()-today.getTime())/1000/60/60/24); // offset from today
    if(iday>=0 && iday<spc.maxDays){
      ihour=Math.floor(prog.start/10000);
      if(ihour<spc.dayStartTime){ ihour=ihour+24; }
      wtable[ihour][iday][wtable[ihour][iday].length]=pi;
    }
  }

  return new Array(now,wtable);

}

function show_program_table(spc){
//
//
//
//
 
  _wtable=make_table_of_program(spc);
  var t=program_table_with_scale(_wtable[0],_wtable[1],spc);

  var writeTo=document.getElementById(spc.writeToId);
  writeTo.innerHTML="";
  writeTo.appendChild(t);

}

function epgTime2Time(startDate,startTime,duration){
//
// EPG形式から Date を作成
//

  var d=new Date(Math.floor(startDate/10000)
                ,Math.floor(startDate/100)%100-1
                ,startDate%100
                ,Math.floor(startTime/10000)
                ,Math.floor(startTime/100)%100
                ,startTime%100);

  d.setTime(d.getTime()+duration*1000);

  return d;

}

function program_div(p){
//
// div でフォーマットされた番組情報を返す
// p: 番組情報
//

  var div_content=document.createElement("div");
  var span_time=document.createElement("span");
  var span_title=document.createElement("span");
  var span_desc=document.createElement("span");
  var link_now=document.createElement("a");

  //var div_content_style_cssText="padding: 0.2em 0.2em 0.2em 1em; text-indent: -1em;"
  var div_content_style_cssText="padding: 0.2em 0.2em 0.2em 0.2em;";
  span_desc.style.cssText="color: gray; font-size: 0.7em;"

  //
  // 今やってる番組の色を替える。2分ほど早く。
  // 2分なら決して遅れることはない。
  //
  var b=new Date();
  b.setTime(b.getTime()+120000);

  var startTime=epgTime2Time(p.date,p.start,0);
  var endTime=epgTime2Time(p.date,p.start,p.duration);

  if(b.getTime()>=startTime.getTime() && b.getTime()<endTime.getTime()){
    div_content_style_cssText=div_content_style_cssText
                              +"background-color: #ffff99;";
    link_now.setAttribute("name","now");
    span_time.appendChild(link_now);
  }

  if(Math.floor(p.start/100)%100==0){
    div_content_style_cssText=div_content_style_cssText
                              +"border-style: solid none none none;"
                              +"border-color: #9966ff;"
                              +"border-width: 0.02em;";
  }

  span_time.appendChild(document.createTextNode(Math.floor(p.start/10000)%100+"."));

  div_content.style.cssText=div_content_style_cssText;

  span_time.appendChild(document.createTextNode(("0"+Math.floor(p.start/100)%100).slice(-2)+" "));
  span_time.style.cssText="color: #0066ff; font-size: 0.8em;";
  span_title.appendChild(document.createTextNode(p.title));
  span_desc.appendChild(document.createTextNode(p.desc));
  div_content.appendChild(span_time);
  div_content.appendChild(span_title);
  div_content.appendChild(span_desc);

  return div_content;

}


function formatDate(d){
//
// フォーマットした日付を返す
//


  var p_string=" "+(d.getMonth()+1)
                  +"/"+d.getDate()+"("
                  +["日","月","火","水","木","金","土"][d.getDay()]+")";


  return p_string;

}

function day_comment(offset){

  if(offset==0){ return "きょう"; }
  else if(offset==1){ return "あす"; }
  else if(offset==2){ return "あさって"; }
  else{ return "" };

}

function tr_date(start,spc){
//
//
//

  var tr_date=document.createElement("tr");
  var d=new Date()
  d.setTime(start.getTime());
  for(id=0;id<spc.maxDays;id++){
    var th_date=document.createElement("th");
    th_date.setAttribute("colSpan",2);
    th_date.style.cssText="background-color: "+spc.wday_color[d.getDay()]+";";
    th_date.appendChild(document.createTextNode(day_comment(id)+formatDate(d)));
    tr_date.appendChild(th_date);
    d.setTime(d.getTime()+60*60*24*1000);
  }

  return tr_date;

}

function program_table_with_scale(startDate,wtable,spc){
//
// 時間表示つきの番組表を table で返す
//

  var table=document.createElement("table");
  var tbody=document.createElement("tbody");
  var d=new Date();

  table.style.cssText="background-color: white;";
  table.appendChild(tbody);

  tbody.appendChild(tr_date(startDate,spc));

  for(hour=spc.dayStartTime;hour<spc.dayStartTime+24;hour++){ // hour index

    var tr=document.createElement("tr");
    d.setTime(startDate.getTime());

    for(day=0;day<spc.maxDays;day++){
      var td_hour=document.createElement("th");
      var td_content=document.createElement("td");
      var span_date=document.createElement("span");

      span_date.appendChild(document.createTextNode(day_comment(day)+formatDate(d)));
      span_date.style.cssText="font-weight: normal; font-size: 60%";

      //td_content.style.cssText="vertical-align: top; text-indent: -1em;";
      td_content.style.cssText="vertical-align: top;"
                               +"background-color: "+spc.wday_p_color[d.getDay()] +";";

      td_hour.appendChild(document.createTextNode(Number(hour)));
      td_hour.appendChild(document.createElement("br"));
      td_hour.appendChild(span_date);

      td_hour.style.cssText="text-align: center; width: 1em; font-size: 120%;"
                            +" background-color: "+spc.hour_bg_color[hour-spc.dayStartTime]+";"
                            +" color: "+spc.hour_color[hour-spc.dayStartTime]+";";

      tr.appendChild(td_hour);

      for(pi in wtable[hour][day]){ // progmras in hour
        var program=spc.programs[wtable[hour][day][pi]];
        td_content.appendChild(program_div(program));
      }
      tr.appendChild(td_content);
      tbody.appendChild(tr);
      d.setTime(d.getTime()+60*60*24*1000);

    }
  }

  return table;

}

function update(id){

  // alert("update: " +id);

  g[id].req=makeRequest(); // リクエストオブジェクトを作成
  // ? 以降はキャッシュを無効にするためにつけてます。
  g[id].req.open('GET',g[id].url+"?"+(new Date()).getTime());
  g[id].req.onreadystatechange=function(){
    if(g[id].req.readyState==4 && g[id].req.status==200){
      epg_week(g[id]);
      setTimeout(function(){update(id)},60000);
    }
  }
  g[id].req.send(null);

}

function week_program(id,url,writeToId,dayStartTime,maxDays){
//
// 番組表を表示するためにデータをリクエストする
//

  g[id]=new Array();       // 名前空間を作成

  g[id].id=id;
  g[id].url=url;
  g[id].writeToId=writeToId;
  g[id].dayStartTime=dayStartTime;
  g[id].maxDays=maxDays;

  update(id);

}


