/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) MIND Co., Ltd.       http://www.e-mind.co.jp/
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package jp.mosp.common.common;

import java.util.List;

/**
 * HTML作成に有用なメソッドを提供する。<br><br>
 * HTMLのヘッダーやフッター等、標準化されたHTMLを作成するのに役立つ。<br>
 */
public class HtmlUtility {
	
	/**
	 * HTMLヘッダー出力。<br>
	 * HTMLヘッダー及びJavascript、cssの宣言を出力する。<br>
	 * JSPの最初に実行することを想定している。<br>
	 * @param vo                情報保持VO
	 * @return HTMLヘッダー文字列
	 * @throws IllegalAccessException
	 */
	public static String getHeader(VoInterface vo) throws IllegalAccessException {
		List<String> extraCss = vo.getExtraCss();
		List<String> extraJs  = vo.getExtraJs ();
		StringBuffer sb = new StringBuffer();
		sb.append("<?xml version=\"1.0\" encoding=\"Shift_JIS\" ?>");
		sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
		sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"ja\">");
		sb.append("<head>");
		sb.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">");
		sb.append("<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\">");
		sb.append("<meta name=\"robots\" content=\"noindex,nofollow,noarchive\" />");
		sb.append("<title>");
		sb.append(vo.getEscTitle());
		sb.append("&nbsp;");
		sb.append(vo.getEscVersion());
		sb.append("</title>");
		sb.append("<link href=\"..");
		sb.append(vo.getEscCommonCss());
		sb.append("\" rel=\"stylesheet\" type=\"text/css\" />");
		if (extraCss != null) {
			for (int i = 0; i < extraCss.size(); i++) {
				sb.append("<link href=\"..");
				sb.append(escapeHTML(extraCss.get(i)));
				sb.append("\" rel=\"stylesheet\" type=\"text/css\" />");
			}
		}
		sb.append("<script type=\"text/javascript\" src=\"..");
		sb.append(MospConst.JS_COMMON);
		sb.append("\"></script>");
		sb.append("<script type=\"text/javascript\" src=\"..");
		sb.append(MospConst.JS_MESSAGE);
		sb.append("\"></script>");
		if (extraJs != null) {
			for (int i = 0; i < extraJs.size(); i++) {
				sb.append("<script type=\"text/javascript\" src=\"..");
				sb.append(escapeHTML(extraJs.get(i)));
				sb.append("\"></script>");
			}
		}
		sb.append("<script type=\"text/javascript\">");
		try {
			sb.append(vo.getDirectJs(vo.getClass()));
		} catch (NullPointerException e) {
			sb.append(vo.getDirectJs(vo.getClass(), vo));
		}
		if (vo.getIsDialog()) {
			sb.append("isDialog = true;");
		}
		sb.append("</script>");
		sb.append("</head>");
		sb.append("<body id=\"base\" onLoad=\"onLoad()\" onUnload=\"onUnload()\">");
		sb.append("<form name=\"form\">");
		return sb.toString();
	}
	
	/**
	 * HTMLフッター出力。<br>
	 * HTMLフッター及びMosPフレームワークで用いる
	 * リクエストパラメータフィールドを出力する。<br>
	 * JSPの最後に実行することを想定している。<br>
	 * @param vo 情報保持VO
	 * @return HTMLフッター文字列
	 */
	public static String getFooter(VoInterface vo){
		StringBuffer sb = new StringBuffer();
		sb.append("<input type=\"hidden\" name=\"");
		sb.append(MospConst.PRM_CMD);
		sb.append("\" value=\"\" />");
		sb.append("<input type=\"hidden\" name=\"");
		sb.append(MospConst.PRM_KEY1);
		sb.append("\" value=\"\" />");
		sb.append("<input type=\"hidden\" name=\"");
		sb.append(MospConst.PRM_KEY2);
		sb.append("\" value=\"\" />");
		sb.append("<input type=\"hidden\" name=\"");
		sb.append(MospConst.PRM_PROC_SEQ);
		sb.append("\" id=\"");
		sb.append(MospConst.PRM_PROC_SEQ);
		sb.append("\" value=\"");
		sb.append(vo.getEscProcSeq());
		sb.append("\" />");
		sb.append("<input type=\"hidden\" name=\"");
		sb.append(MospConst.PRM_RESPONSE_TYPE);
		sb.append("\" value=\"\" />");
		sb.append("</form>");
		sb.append("</body>");
		sb.append("</html>");
		return sb.toString();
	}
	
	/**
	 * HTMLメッセージ出力。<br>
	 * 任意の位置に、メッセージを配置する。<br>
	 * @param vo 情報保持VO
	 * @return HTMLメッセージ文字列
	 */
	public static String getMessages(VoInterface vo) {
		StringBuffer sb = new StringBuffer();
		List<String> errMessage = vo.getErrMessage();
		if (vo.getEscMessage() != null && !vo.getEscMessage().equals("")) {
			sb.append("<div class=\"MessageLabel\" id=\"lblMessage\">");
			sb.append(vo.getEscMessage());
			sb.append("</div>");
		}
		if (errMessage != null && errMessage.size() > 0) {
			sb.append("<div class=\"ErrorMessageLabel\" id=\"lblErrorMessage\">");
			for (int i = 0; i < errMessage.size(); i++) {
				sb.append(errMessage.get(i));
				sb.append("<br />");
			}
			sb.append("</div>");
		}
		return sb.toString();
	}

	/**
	 * リスト情報出力。<br>
	 * 一覧の件数及び前頁、次頁ボタンを出力する。<br>
	 * @param vo 情報保持VO
	 * @return HTMLリスト情報文字列
	 */
	public static String getListInfo(ListVo vo) {
		StringBuffer sb = new StringBuffer();
		sb.append("<div class=\"ListInfo\">");
		sb.append("<table>");
		sb.append("<tr>");
		sb.append("<td>");
		if (vo.getNeedFormer()) {
			sb.append("<button type=\"button\" onclick=\"doSubmit(document.form, '");
			sb.append(MospConst.CMD_LIST_FORMER);
			sb.append("')\">");
		} else {
			sb.append("<button type=\"button\" disabled=\"disabled\">");
		}
		sb.append("前頁</button>");
		sb.append("</td>");
		if (vo.getCount() != 0) {
			sb.append("<td>");
			sb.append(vo.getStart() + 1);
			sb.append("&nbsp;〜&nbsp;");
			sb.append(vo.getEnd() + 1);
			sb.append("&nbsp;/&nbsp;");
			sb.append(vo.getCount());
			sb.append("&nbsp件");
			sb.append("</td>");
		}
		sb.append("<td>");
		if (vo.getNeedNext()) {
			sb.append("<button type=\"button\" onclick=\"doSubmit(document.form, '");
			sb.append(MospConst.CMD_LIST_NEXT);
			sb.append("')\">");
		} else {
			sb.append("<button type=\"button\" disabled=\"disabled\">");
		}
		sb.append("次頁</button>");
		sb.append("</td>");
		sb.append("</tr>");
		sb.append("</table>");
		sb.append("</div>");
		return sb.toString();
	}
	
	/**
	 * リスト情報出力。<br>
	 * 一覧の件数及び前頁、次頁ボタンを出力する。<br>
	 * 任意の頁に遷移できる機能を持つ。<br>
	 * @param vo 情報保持VO
	 * @return HTMLリスト情報文字列
	 */
	public static String getListInfoFlex(ListVo vo) {
		StringBuffer sb = new StringBuffer();
		String command = vo.getPageCommand();
		int    select  = vo.getSelectIndex();
		int    full    = vo.getCountAllData() / vo.getDataPerPage();
		int    end     = vo.getOffset() + vo.getDataPerPage();
		if (vo.getCountAllData() % vo.getDataPerPage() != 0) {
			full++;
		}
		end = end > vo.getCountAllData() ? vo.getCountAllData() : end;
		sb.append("<div class=\"ListPageInfo\">");
		sb.append("<div>");
		sb.append(vo.getCountAllData() == 0 ? 0 : vo.getOffset() + 1);
		sb.append("&nbsp;〜&nbsp;");
		sb.append(end);
		sb.append("&nbsp;/&nbsp;");
		sb.append(vo.getCountAllData());
		sb.append("&nbsp件");
		sb.append("</div>");
		if (vo.getCountAllData() <= vo.getDataPerPage()) {
			sb.append("</div>");
			return sb.toString();
		}
		sb.append("<table>");
		sb.append("<tr>");
		sb.append("<td>");
		if (select - 1 > 0) {
			sb.append("<button type=\"button\" onclick=\"doSubmitKey(document.form, '");
			sb.append(command);
			sb.append("', '");
			sb.append(select - 1);
			sb.append("', '')\">");
		} else {
			sb.append("<button type=\"button\" disabled=\"disabled\">");
		}
		sb.append("前頁</button>");
		sb.append("</td>");
		if (full != 0) {
			int pageNum = select / MospConst.COUNT_PAGE_BUTTON * MospConst.COUNT_PAGE_BUTTON;
			for (int i = -1; i < MospConst.COUNT_PAGE_BUTTON + 1; i++) {
				if (pageNum + i > 0 && pageNum + i <= full) {
					if (select != pageNum + i) {
						sb.append("<td><button type=\"button\" class=\"ButtonListPage\" ");
						sb.append("onclick=\"doSubmitKey(document.form, '");
						sb.append(command);
						sb.append("', '");
						sb.append(pageNum + i);
						sb.append("', '')\">");
						sb.append(pageNum + i);
						sb.append("</button></td>");
					} else if (select == pageNum + i) {
						sb.append("<td>");
						sb.append(pageNum + i);
						sb.append("頁</td>");
					}
				}
			}
		}
		sb.append("<td>");
		if (select + 1 <= full) {
			sb.append("<button type=\"button\" onclick=\"doSubmitKey(document.form, '");
			sb.append(command);
			sb.append("', '");
			sb.append(select + 1);
			sb.append("', '')\">");
		} else {
			sb.append("<button type=\"button\" disabled=\"disabled\">");
		}
		sb.append("次頁</button>");
		sb.append("</td>");
		sb.append("</tr>");
		sb.append("</table>");
		sb.append("</div>");
		return sb.toString();
	}
	
	/**
	 * MosP利用権限セレクトオプション出力。<br>
	 * MosPフレームワーク標準のMosP利用権限セレクトオプションを出力する。<br>
	 * @param mospAuthority 選択MosP利用権限
	 * @return HTMLMosP利用権限セレクトオプション文字列
	 */
	public static String getMospAuthSelectOption(String mospAuthority) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < MospConst.AUTH_MOSP_VALUE.length; i++) {
			String selected = "";
			if (mospAuthority != null && mospAuthority.equals(MospConst.AUTH_MOSP_VALUE[i])) {
				selected = "selected=\"selected\"";
			}
			sb.append("<option value=\"");
			sb.append(MospConst.AUTH_MOSP_VALUE[i]);
			sb.append("\"");
			sb.append(selected);
			sb.append(">");
			sb.append(MospConst.AUTH_MOSP_TITLE[i]);
			sb.append("</option>");
		}
		return sb.toString();
	}
	
	/**
	 * 削除フラグセレクトオプション出力。<br>
	 * MosPフレームワーク標準の削除フラグセレクトオプションを出力する。<br>
	 * @param deleteFlag 削除フラグ
	 * @return HTMLMosP削除フラグセレクトオプション文字列
	 */
	public static String getDeleteFlagSelectOption(String deleteFlag) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < MospConst.DELETE_FLAG_VALUE.length; i++) {
			String selected = "";
			if (deleteFlag != null && deleteFlag.equals(MospConst.DELETE_FLAG_VALUE[i])) {
				selected = "selected=\"selected\"";
			}
			sb.append("<option value=\"");
			sb.append(MospConst.DELETE_FLAG_VALUE[i]);
			sb.append("\"");
			sb.append(selected);
			sb.append(">");
			sb.append(MospConst.DELETE_FLAG_TITLE[i]);
			sb.append("</option>");
		}
		return sb.toString();
	}
	
	/**
	 * セレクトオプション出力。<br>
	 * 任意のセレクトオプションを出力する。<br>
	 * @param array セレクトオプション内容
	 * @param value 初期選択値
	 * @return HTMLセレクトオプション文字列
	 */
	public static String getSelectOption(String[][] array, String value) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < array.length; i++) {
			String selected = "";
			if (array[i][0].equals(value)) {
				selected = "selected=\"selected\"";
			}
			sb.append("<option value=\"");
			sb.append(escapeHTML(array[i][0]));
			sb.append("\"");
			sb.append(selected);
			sb.append(">");
			sb.append(escapeHTML(array[i][1]));
			sb.append("</option>");
		}
		return sb.toString();
	}

	/**
	 * 必須マーク出力。<br>
	 * MosPフレームワーク標準の必須マークを出力する。<br>
	 * @return HTML必須マーク文字列
	 */
	public static String getRequiredMark() {
		return "<span class=\"RequiredLabel\">*&nbsp;</span>";
	}
	
	/**
	 * プルダウンリスト。<br>
	 * 任意のプルダウンリストを出力する。<br>
	 * @param aryPulldown プルダウン用配列
	 * @return プルダウンリスト文字列
	 */
	public static String getPulldownList(String[][] aryPulldown) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < aryPulldown.length; i++) {
			sb.append("<option value=\"");
			sb.append(aryPulldown[i][0]);
			sb.append("\">");
			sb.append(aryPulldown[i][1]);
			sb.append("</option>");
		}
		return sb.toString();
	}
	
	/**
	 * HTMLエスケープ。<br>
	 * @param aStr エスケープ対象文字列
	 * @return エスケープ後文字列
	 */
	public static String escapeHTML(String aStr) {
		char c;
		String strTarget = aStr != null ? aStr : "";
		StringBuffer returnStr = new StringBuffer();
		int length = strTarget.length();
		for (int i = 0; i < length; i++) {
			c = strTarget.charAt(i); 
			if (c == '<') {
				returnStr = returnStr.append("&lt;");
			} else if(c == '>') {
				returnStr = returnStr.append("&gt;");
			} else if(c == '&') {
				returnStr = returnStr.append("&amp;");
			} else if(c == '"') {
				returnStr = returnStr.append("&quot;");
			} else if(c == '\'') {
				returnStr = returnStr.append("&#39;");
			} else {
				returnStr = returnStr.append(c);
			}
		}
		return new String(returnStr);
	}
	
	/**
	 * メインタイトル取得。<br>
	 * ログイン画面、メニューガイド画面等で用いるタイトルバーのHTMLを取得する。
	 * @param vo           メインタイトル取得元VO
	 * @param extraTitle   追加タイトル
	 * @param guideCommand メニューガイドボタンコマンド(nullの場合ボタン非表示)
	 * @param guideTitle   メニューガイドボタンタイトル
	 * @param needLogout   ログインボタン要否(true：要、false：不要)
	 * @return メインタイトルHTML文字列
	 */
	public static String getMainTitle(
			BaseVo vo, String extraTitle, String guideCommand, String guideTitle, boolean needLogout
	) {
		// HTML作成
		StringBuffer sb = new StringBuffer();
		sb.append("<div class=\"Header\">");
		// ロゴバー
		sb.append("<div class=\"LogoBar\">");
		sb.append(getTagLogoImage(vo.getLogoPath(), vo.getName("C_LOGO")));
		sb.append("</div>");
		// ボタンバー
		sb.append("<div class=\"MenuButtonBar\">");
		if (guideCommand != null) {
			sb.append(getButtonTag("btnGuide", guideCommand, guideTitle));
		}
		if (needLogout) {
			sb.append(getButtonTag("btnLogout", MospConst.CMD_LOGOUT, vo.getName("C_LOGOUT")));
		}
		sb.append("</div>");
		sb.append("<div class=\"TitleBar\">");
		sb.append("<span id=\"lblTitle\">");
		sb.append(vo.getEscTitle() + "&nbsp;");
		if (extraTitle != null) {
			sb.append(extraTitle + "&nbsp;");
		}
		sb.append("</span>");
		sb.append("<span id=\"lblVersion\">" + vo.getEscVersion() + "</span>");
		if (vo.getEscUserName() != null && !vo.getEscUserName().equals("")) {
			sb.append("<span id=\"lblUserName\">");
			sb.append(vo.getName("C_USER") + vo.getName("C_NAME") + vo.getName("C_SEPARATOR"));
			sb.append(vo.getEscUserName() + "</span>");
		}
		sb.append("</div>");
		sb.append("</div>");
		return sb.toString();
	}
	
	/**
	 * サブタイトル取得。<br>
	 * @param vo サブタイトル取得元VO
	 * @return サブタイトルHTML文字列
	 */
	public static String getSubTitle(BaseVo vo) {
		String[][] aryMenu = vo.getAryMenu();
		StringBuffer sb = new StringBuffer();
		sb.append("<div class=\"Header\">");
		sb.append("<div class=\"LogoBar\">");
		sb.append(getTagLogoImage(vo.getLogoPath(), vo.getName("C_LOGO")));
		sb.append("</div>");
		sb.append("<div class=\"MenuButtonBar\">");
		if (aryMenu != null) {
			for (int i = 1; i < aryMenu.length; i++) {
				sb.append(getButtonTag("btnMenu" + i, aryMenu[i][0], aryMenu[i][1]));
			}
			sb.append(getButtonTag("btnMenu", aryMenu[0][0], aryMenu[0][1]));
		}
		sb.append(getButtonTag("btnLogout", MospConst.CMD_LOGOUT, vo.getName("C_LOGOUT")));
		sb.append("</div>");
		sb.append("<div class=\"SubTitleBar\">");
		sb.append(vo.getSubTitle());
		sb.append("</div>");
		sb.append("</div>");
		return sb.toString();
	}
	
	/**
	 * ボタンタグ取得。<br>
	 * @param id   id
	 * @param cmd  コマンドNo.
	 * @param name ボタン名称
	 * @return ボタンタグHTML文字列
	 */
	public static String getButtonTag(String id, String cmd, String name) {
		StringBuffer sb = new StringBuffer();
		sb.append("<button type=\"button\" ");
		if (id.length() != 0) {
			sb.append("id=\"");
			sb.append(id);
			sb.append("\"");
		}
		sb.append(" onclick=\"doSubmit(document.form, '");
		sb.append(cmd);
		sb.append("')\">");
		sb.append(name);
		sb.append("</button>");
		return sb.toString();
	}
	
	/**
	 * ロゴイメージタグ取得。<br>
	 * @param logoPath ロゴファイルパス
	 * @param namLogo  ロゴファイルタイトル
	 * @return ロゴイメージタグHTML文字列
	 */
	public static String getTagLogoImage(String logoPath, String namLogo) {
		StringBuffer sb = new StringBuffer();
		if (logoPath != null) {
			sb.append("<img class=\"Logo\" id=\"logo\" src=\"");
			sb.append(MospConst.URL_PUB + logoPath);
			sb.append("\" alt=\"" + namLogo + "\">");
		}
		return sb.toString();
	}
	
}
