/*
 * SampleCalendarTag.java
 *
 * Created on 2006/12/14, 9:47
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.itscool.stylist.function;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.itscool.commons.util.DateElement;
import org.itscool.commons.util.DateFormatUtil;
import org.itscool.commons.util.MonthTable;

/**
 * <p>
 * カレンダーを表示するEL関数です。<br/>
 * 呼び出し側で以下のEL関数を記述すると、<br>
 * </p>
 *
 * <p>
 * ${dateC.draw(DateオブジェクトもしくはDateオブジェクトのtoString())｝
 * </p>
 *
 * 以下のような文字列を生成します。<br>
 * <p>
 * <pre>
 * &lt;table class="calendar"&gt;
 * &lt;tr&gt;
 *     &lt;td class="header"&gt;日&lt;/td&gt;
 *     &lt;td class="header"&gt;月&lt;/td&gt;
 *     &lt;td class="header"&gt;火&lt;/td&gt;
 *     &lt;td class="header"&gt;水&lt;/td&gt;
 *     &lt;td class="header"&gt;木&lt;/td&gt;
 *     &lt;td class="header"&gt;金&lt;/td&gt;
 *     &lt;td class="header"&gt;土&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;tr&gt;
 * &lt;tr&gt;
 *     &lt;td class="sunday" align="center"&gt;25&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;26&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;27&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;28&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;1&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;2&lt;/td&gt;
 *     &lt;td class="saturday" align="center"&gt;3&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;tr&gt;
 *     &lt;td class="sunday" align="center"&gt;4&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;5&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;6&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;7&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;8&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;9&lt;/td&gt;
 *     &lt;td class="saturday" align="center"&gt;10&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;tr&gt;
 *     &lt;td class="sunday" align="center"&gt;11&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;12&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;13&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;14&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;15&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;16&lt;/td&gt;
 *     &lt;td class="saturday" align="center"&gt;17&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;tr&gt;
 *     &lt;td class="sunday" align="center"&gt;18&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;19&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;20&lt;/td&gt;
 *     &lt;td class="holiday" align="center"&gt;21&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;22&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;23&lt;/td&gt;
 *     &lt;td class="saturday" align="center"&gt;24&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;tr&gt;
 *     &lt;td class="sunday" align="center"&gt;25&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;26&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;27&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;28&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;29&lt;/td&gt;
 *     &lt;td class="day" align="center"&gt;30&lt;/td&gt;
 *     &lt;td class="saturday" align="center"&gt;31&lt;/td&gt;
 * &lt;/tr&gt;
 * &lt;/table&gt;
 * </pre>
 * </p>
 * @author kanou
 */
public class CalendarC {
    public static final String LINE = "\n";
    public static final String TAB = "    ";
    
    StringBuffer sb = new StringBuffer();
    
    /**
     * 引数に指定された日付データからカレンダー表示文字列を取得します
     * @param date Dateインスタンス
     * @return カレンダー表示文字列
     */
    public String draw(Date date) {
        if( date == null ){
            return "";
        }
        MonthTable month = new MonthTable(date);
        if(month == null){
            month = new MonthTable();
        }
        StringBuffer sb = new StringBuffer();
        //カレンダー表示部
        sb.append(createMonthTag(month));
        
        return sb.toString();
    }
    
    public String draw(String dateStr){
        if( dateStr == null || dateStr.length() == 0 ){
            return "";
        }
        try{
            Date date = DateFormatUtil.parse(dateStr);
            return draw(date);
        }catch(Exception e){
            return "CalendarC.draw()" + e.getMessage();
        }
    }
    
    /**
     * Monthテーブルを作成します
     * @param month MonthTableインスタンス
     * @return 月単位のカレンダー表示文字列
     */
    protected String createMonthTag(MonthTable month){
        StringBuffer sb = new StringBuffer();
        DateElement day = month.getDay(month.getYear(), month.getMonth(), 1);
        
        sb.append("<table class=\"calendar\">").append(LINE);
        sb.append(createHeader());
        int firstYobi = day.getYobi();
        if(firstYobi != Calendar.SUNDAY){
            Calendar cal = DateFormatUtil.getLastMonthWeek(month.getYear(), month.getMonth());
            sb.append("<tr>").append(LINE);
            for(int i=1; i<firstYobi; i++, cal.add(Calendar.DAY_OF_MONTH, 1)){
                day = month.getDay(cal);
                sb.append(createDayTag(day));
            }
        }
        for(int i=0; i<month.getMaxday(); i++){
            day = month.getDay(month.getYear(), month.getMonth(), i+1);
            sb.append(createDayTag(day));
        }
        DateElement lastDay = month.getDay(month.getYear(), month.getMonth(), month.getMaxday());
        if(lastDay.getYobi() != Calendar.SATURDAY){
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, month.getYear());
            cal.set(Calendar.MONTH, month.getMonth()-1);
            cal.set(Calendar.DAY_OF_MONTH, month.getMaxday());
            cal.add(Calendar.DAY_OF_MONTH, 1);
            for(int i=lastDay.getYobi(); i<Calendar.SATURDAY; i++, cal.add(Calendar.DAY_OF_MONTH, 1)){
                day = month.getDay(cal);
                sb.append(createDayTag(day));
            }
            if( day.getYobi() != Calendar.SATURDAY ){
                sb.append("</tr>").append(LINE);
            }else{
                sb.append(LINE);
            }
        }
        sb.append("</table>");
        return sb.toString();
    }
    
    /**
     * Day要素を作成します
     * @param day DateElementインスタンス
     * @return 日付表示文字列を返します
     */
    protected String createDayTag(DateElement day){
        StringBuffer sb = new StringBuffer();
        if(day.getYobi() == Calendar.SUNDAY){
            sb.append("<tr>").append(LINE);
        }
        if( day.isHoliday() ){
            sb.append(TAB).append("<td class=\"holiday\" align=\"center\">");
        }else if(day.getYobi() == Calendar.SUNDAY){
            sb.append(TAB).append("<td class=\"sunday\" align=\"center\">");
        }else if(day.getYobi() == Calendar.SATURDAY){
            sb.append(TAB).append("<td class=\"saturday\" align=\"center\">");
        }else{
            sb.append(TAB).append("<td class=\"day\" align=\"center\">");
        }
        sb.append(createDayBodyContents(day));
        
        sb.append("</td>").append(LINE);
        if( day.getYobi() == Calendar.SATURDAY ){
            sb.append("</tr>").append(LINE);
        }
        return sb.toString();
    }
    
    /**
     * 日付要素の中身を出力します（サブクラスでオーバーライドして使えます)
     * @param day DateElement 要素
     * @return 日付要素の中身を返します
     */
    protected String createDayBodyContents(DateElement day){
        String body = String.valueOf(day.getDay());
        return body;
    }
    
    /**
     * カレンダーテーブルのヘッダ部分を作成する
     * @return カレンダーテーブルのヘッダ部分
     */
    protected String createHeader(){
        StringBuffer sb = new StringBuffer();
        sb.append("<tr>");
        sb.append(LINE);
        StringBuffer td = new StringBuffer();
        td.append(TAB);
        td.append("<td class=\"header\">");
        
        sb.append(td.toString()).append("日").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("月").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("火").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("水").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("木").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("金").append("</td>");
        sb.append(LINE);
        sb.append(td.toString()).append("土").append("</td>");
        sb.append(LINE);
        sb.append("</tr>").append(LINE);
        return sb.toString();
    }
    
}
