/*********************************************************************************************************
 * 프로그램명 : TagFilter.java 프로그램설명 : 프로젝트와 관련된 정보를 얻을수 있는 class 작성자 : 강원중 작성일 : 2004.01.06 변경일 : 2003.11.30
 **********************************************************************************************************/

package kr.co.kihyun.text.html;

import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.IOException;
import java.util.StringTokenizer;
import kr.co.kihyun.lang.MString;
import kr.co.kihyun.moumi.MoumiConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HtmlUtil {
        private static final Logger LOG = LoggerFactory.getLogger(HtmlUtil.class);
    
      //v2. 5.static final 필드 변조 가능성 : Update by KWON,HAN 
//	public static final String innerTableMark = "!#_";
        private static final String innerTableMark = "!#_";    
      //==========================================================
        
	String table = "";
	StringBuffer innerTableBuf = new StringBuffer();

	public static int getTableCount(String form) {

		// form = form.toLowerCase();
		int tableCount = 0;
		int stIndex = 0;
		String stTABLE = "<table";
		stIndex = form.indexOf(stTABLE);
		while (true) {

			if (stIndex == -1)
				break;
			tableCount++;
			stIndex = form.indexOf(stTABLE, stIndex + stTABLE.length());
		}

		return tableCount;
	}

	public String getTable() {
		return table;
	}

	public String getInnerTables() {
		return innerTableBuf.toString();
	}

	/**************************** 하나의 HTML file내의 tables를 추출해서 배열에 저장함 ****************************/
	public static String[] getTableList(String html) throws NullPointerException {
		return getTableList(new StringBuilder(html));
	}

	public static String[] getTableList(StringBuilder html) throws NullPointerException {

		int count = 0;

		int strIndex = 0;
		int endIndex = 0;
		String stTag = "<table";
		String edTag = "</table>";
		String[] tableList = null;

		// table count
		for (count = 0; true; count++) {
			if (count > 0) {
				strIndex = html.indexOf(stTag, strIndex + stTag.length());
			} else {
				strIndex = html.indexOf(stTag, strIndex);
			}
			endIndex = html.indexOf(edTag, strIndex);
			if (strIndex == -1 || endIndex == -1)
				break;
		}

		// table 수 만큼 배열 생성
		tableList = new String[count];

		// table 추출 미리 생성해놓은 배열에 입력
		strIndex = 0;
		endIndex = 0;
		for (int i = 0; true; i++) {
			if (i > 0) {
				strIndex = html.indexOf(stTag, strIndex + stTag.length());
			} else {
				strIndex = html.indexOf(stTag, strIndex);
			}
			endIndex = html.indexOf(edTag, strIndex);

			if (strIndex == -1 || endIndex == -1)
				break;
			tableList[i] = (html.substring(strIndex, endIndex + edTag.length())).toString();
		}

		return tableList;
	}

	/**************************** tag 내의 넒이 추출 ****************************/
	public static int getWidth(String tag) throws NumberFormatException {
		// height 추출
		String strTag = Html.width + "=\"";
		String endTag = "px";
		int size = 0;

		int strIndex = tag.indexOf(strTag);
		int endIndex = tag.indexOf(endTag, strIndex);

		if (strIndex > -1 && endIndex > -1 && tag.length() > endIndex && tag.length() > strIndex) {
			size = Integer.parseInt(tag.substring((strIndex + strTag.length()), endIndex).trim());
		}

		return size;
	}

	/**************************** tag 내의 높이 추출 ****************************/
	public static int getHeight(String tag) throws NumberFormatException {
		// height 추출
		String strTag = Html.height + "=\"";
		String endTag = "px";
		int size = 0;

		int strIndex = tag.indexOf(strTag);
		int endIndex = tag.indexOf(endTag, strIndex);

		if (strIndex > -1 && endIndex > -1 && tag.length() > endIndex && tag.length() > strIndex) {
			size = Integer.parseInt(tag.substring((strIndex + strTag.length()), endIndex).trim());
		}

		return size;
	}

	public String getTableHtml(String form) { // 폼에서 <Table>테그 부터 </table>까지만 잘라서 반환하는 함수
		String result = "";

		int stTABLE = form.indexOf("<table");
		result = form.substring(stTABLE, form.length());
		return result;
	}

	// 표만 받아오는 로직
	public static String getTableHtmlSpace(String htm) {
		// String htm = htm.toLowerCase();
		String result = "";

		int st_table = 0;
		int ed_table = 0;
		st_table = htm.indexOf("<table", st_table);
		while (st_table >= 0) {

			if (st_table == -1)
				break;
			ed_table = htm.indexOf("</table>", ed_table + 8);
			result = result + htm.substring(st_table, ed_table + 8) + "<br>";
			st_table = htm.indexOf("<table", st_table + 2);
		}

		int ed_tableResult = result.lastIndexOf("<br>");
		result = result.substring(0, ed_tableResult);

		return result;
	}

	// 문서의 마지막 표 다음(꼬리) 부분을 잘라줌
	public static String getTailForm(String form) {

		if (form == null) {
			return form;
		}

		// form = form.toLowerCase();
		int strIndex = form.lastIndexOf("</table>");

		if (strIndex < 0) {
			return form;
		}

		return form.substring(strIndex);
	}

	// width= 에다가 100%를 넣으려고...하는 로직 과 <table과 <table사이에 <br>넣는 로직
	public String getInsertWidth(String form) {
		String result = null;
		result = form;
		int stTABLE = 0;
		int stWidth = 0;
		String endResult = "";
		StringBuffer sInsertedData = new StringBuffer();
		stTABLE = result.indexOf("<table", stTABLE);
		while (true) {

			if (stTABLE == -1)
				break;
			stWidth = result.indexOf("width=", stTABLE);
			if (stWidth == -1)
				break;
			endResult = endResult + result.substring(stTABLE, stWidth + 6);
			endResult = endResult + "100% hh=";
			endResult = endResult + result.substring(stWidth + 6, result.length());
			stTABLE = result.indexOf("<table", stTABLE + 6);
		}

		if (stWidth == -1) {
			// result = endResult;
			endResult = result;
			result = result.toLowerCase();
			endResult = "";
			stTABLE = 0;
			while (true) {
				stTABLE = result.indexOf("<table");
				if (stTABLE == -1)
					break;
				sInsertedData.append(result.substring(0, stTABLE + 6));
				sInsertedData.append(" width=100% ");
				result = result.substring(stTABLE + 6, result.length());
			}
			sInsertedData.append(result);
			endResult = sInsertedData.toString();
		}

		return endResult.replaceAll("style", "ss");
	}

	// 테이블 수 구하는 로직
	public int getTableSu(String form) {
		// ban lower case form = form.toLowerCase();
		int tableSu = 0;
		int fiTABLE = 0;
		while (true) {
			fiTABLE = form.indexOf("<table", fiTABLE);
			if (fiTABLE == -1)
				break;
			tableSu++;
			fiTABLE = fiTABLE + 7;
		}

		return tableSu;
	}

	public String getHwpTo_P(String form) {
		// 이로직은 한글 땜시 있어야 하는 로직 입니다.
		// <p
		// 'font-family:"한컴바탕";font-size:13px;color:"#000000";text-align:justify;line-height:21px;text-indent:0px;margin-left:0px;margin-right:0px;margin-top:0px;margin-bottom:0px;'>
		// 이 <p>태그를 없애야지만 한글에서 표가 일정하게 나옵니다.

		String result = form;
		StringBuffer sInsertedData = new StringBuffer();

		int tdStart = 0;
		int tdEnd = 0;
		int pStart = 0, pEnd = 0;

		while (true) {
			tdStart = result.indexOf("<td");
			if (tdStart == -1)
				break;
			tdEnd = result.indexOf(">", tdStart + 1);
			if (tdEnd == -1)
				break;
			pStart = result.indexOf("<p", tdEnd);
			if (pStart == -1)
				break;
			pEnd = result.indexOf(">", pStart + 2);
			if (pEnd == -1)
				break;
			sInsertedData.append(result.substring(0, pStart));
			result = result.substring(pEnd + 1, result.length());
		}
		sInsertedData.append(result);
		return sInsertedData.toString();// .replaceAll("border=0", "border=1");//.replaceAll("height=", "");

	}

	// ///////////////////////////// Html 삭제 로직 ///////////////////////////////
	public String getDeleteTable(String form, int tableDelete) {// 테이블을 삭제 하기 위한 로직.
		// ban lower case form = form.toLowerCase();
		StringBuffer tmp;
		int stTABLE = 0;
		int edTABLE = 0;
		stTABLE = form.indexOf("<table");
		for (int i = 1; i <= tableDelete; i++) {
			edTABLE = form.indexOf("</table", stTABLE);//
			if (i == tableDelete)
				break;
			stTABLE = form.indexOf("<table", stTABLE + 7);//
		}
		tmp = new StringBuffer(form);
		tmp = tmp.delete(stTABLE, edTABLE + 12);
		return tmp.toString();
	}

	public String getDeleteSubject(String form, int tableLine) {// 사용자가 선택한 라인 부분을 위에서부터 삭제하여 보여주기 위한 함수
		StringBuffer tmp;
		// ban lower case form = form.toLowerCase();

		int fiTABLE = 0;
		int scTABLE = 0;

		for (int i = 1; i < tableLine; i++) {
			fiTABLE = form.indexOf("</table", fiTABLE);//
			fiTABLE = fiTABLE + 7;
			scTABLE = form.indexOf("<table", fiTABLE);//
			scTABLE = scTABLE + 6;
		}

		int stTR = form.indexOf("<tr", scTABLE);
		int edTR = form.indexOf("</tr>", scTABLE);
		int stTD = form.indexOf("<td", scTABLE);

		if (stTR == -1) {
			stTR = stTD;
		} else if (edTR == -1) {
			if (stTR > stTD) {
				edTR = stTR + 1;
				stTR = stTD;
			} else {
				edTR = form.indexOf("<tr", stTR + 2);
			}
		} else if (stTR != -1 && edTR != -1 && stTR > edTR + 5) {
			stTR = stTD;
		}

		tmp = new StringBuffer(form);
		tmp = tmp.delete(stTR, edTR + 5);
		return tmp.toString();
	}

	public String getDeleteSubject2(String form) {
		StringBuffer tmp;
		// ban lower case form = form.toLowerCase();

		int fiTABLE = form.indexOf("</table");// 첫번째 table 끝
		int scTABLE = form.indexOf("<table", fiTABLE);// 두번째 table
		int stTR = form.indexOf("<tr", scTABLE);
		int edTR = form.indexOf("</tr>", scTABLE);
		int stTD = form.indexOf("<td", scTABLE);

		if (stTR == -1) {
			stTR = stTD;
		} else if (edTR == -1) {
			if (stTR > stTD) {
				edTR = stTR + 1;
				stTR = stTD;
			} else {
				edTR = form.indexOf("<tr", stTR + 2);
			}
		} else if (stTR != -1 && edTR != -1 && stTR > edTR + 5) {
			stTR = stTD;
		}
		tmp = new StringBuffer(form);
		tmp = tmp.delete(stTR, edTR + 5);
		return tmp.toString();
	}

	// ///////////////////////////// Html 추가 로직 ///////////////////////////////
	// <table에 cellpadding, cellspacing이 없으면 추가 하는 로직
	public static String getTableHtmlCell(String form) {
		// ban lower case form = form.toLowerCase();
		StringBuffer inBuf = new StringBuffer();
		String endResult = "";
		int stTABLE = 0;
		int cellpadding = form.indexOf("cellpadding");
		int cellspacing = form.indexOf("cellspacing");
		if (cellpadding == -1) {
			while (true) {
				stTABLE = form.indexOf("<table");
				if (stTABLE == -1)
					break;
				inBuf.append(form.substring(0, stTABLE + 6));
				inBuf.append(" cellpadding=0 ");
				form = form.substring(stTABLE + 6, form.length());
			}
			inBuf.append(form);
			endResult = inBuf.toString();
		} else {
			endResult = form.replaceAll("cellpadding=1", "cellpadding=0").replaceAll("cellpadding=\"1\"",
					"cellpadding=\"0\"");
		}

		form = endResult;
		StringBuffer sInsertedData = new StringBuffer();
		if (cellspacing == -1) {
			while (true) {
				stTABLE = form.indexOf("<table");
				if (stTABLE == -1)
					break;
				sInsertedData.append(form.substring(0, stTABLE + 6));
				sInsertedData.append(" cellspacing=0 ");
				form = form.substring(stTABLE + 6, form.length());
			}
			sInsertedData.append(form);
			endResult = sInsertedData.toString();
		} else {
			endResult = form.replaceAll("cellspacing=1", "cellspacing=0").replaceAll("cellspacing=\"1\"",
					"cellspacing=\"0\"");
		}
		return endResult;
	}

	// ///////////////////////////// Html tag 생성기 ///////////////////////////////
	public String getFileLink(String sFileId, String sFileName) {
		if (sFileName.equals("") && sFileId.equals("")) {
			return (MoumiConfig.getMessageBundle().getString("moumi.message.tot_doc.absence"));
		} else {
			return "<a href='../upload/" + sFileId + "'>" + sFileName + "</a>";
		}
	}

	// //////// getData
	// //////////////////////////////////////////////////////////////////////////////////////////////////

	public static String getData(String form) {
		if (form == null)
			return null;

		StringBuffer sb1 = new StringBuffer();
		StringBuffer sb2 = new StringBuffer();
		StringBuffer sb = new StringBuffer();

		String data = "";

		int tableStart = 0;
		int tableEnd = 0;
		int headStart = 0;
		headStart = form.indexOf("<table");

		if (headStart > 0) {
			sb2.append(form.substring(headStart, form.length()));
			form = sb2.toString();
		}

		while (true) {
			tableStart = form.indexOf("<table");
			if (tableStart == -1)
				break;
			tableEnd = form.indexOf(">", tableStart + 1);
			if (tableEnd == -1)
				break;

			sb1.append(form.substring(0, tableStart + 6));
			sb1.append(">");
			form = form.substring(tableEnd + 1, form.length());
		}

		sb1.append(form);
		data = sb1.toString();

		int tdStart = 0;
		int tdEnd = 0;
		int closetdStart = 0;

		while (true) {
			// if ( index > itemIndex.length-1 ) break;
			tdStart = data.indexOf("<td");
			if (tdStart == -1)
				break;
			tdEnd = data.indexOf(">", tdStart + 1);
			if (tdEnd == -1)
				break;
			closetdStart = data.indexOf("</td>", tdEnd + 1);
			if (closetdStart == -1)
				break;
			sb.append(data.substring(0, tdEnd));
			sb.append(" .>");
			sb.append(data.substring(tdEnd + 1, closetdStart));
			sb.append("</td>");
			data = data.substring(closetdStart + 5, data.length());
		}
		sb.append(data);
		return sb.toString();
	}

	// // 개행을 <br>로 바꾸기 위한 메쏘드
      //v2. 5.static final 필드 변조 가능성 : Update by KWON,HAN
      //private는 같은 클래스 내에서만 호출이 가능하므로 접근제한이 없는 public으로 하고 final을 사용하지 않는다
//	public static final String toBR(String tmp2) {
        public static String toBR(String tmp2) {
      //==========================================================
            LOG.debug("v2. 5.static final 필드 변조 가능성 : HtmlUtil.toBR() Not Test {}", tmp2);
            
		String tmp9 = "";

		if (tmp2.indexOf("\n") >= 1) {
			StringTokenizer stk = new StringTokenizer(tmp2, "\n");
			int stkCnt = stk.countTokens();
			for (int fx = 1; fx < stkCnt; fx++) {
				if (fx == 1) {
					tmp9 = (stk.nextToken()).trim();
				} else {
					tmp9 += "<br>" + (stk.nextToken()).trim();
				}
			}
			tmp9 += "<br>" + (stk.nextToken()).trim();
			tmp2 = tmp9;
		}
		return tmp2;
	}

	public static String getTables(String html) throws NullPointerException {
		return getTables(new StringBuffer(html));
	}

	public static String getTables(StringBuffer html) throws NullPointerException {

		int count = 0;

		int strIndex = 0;
		int endIndex = 0;
		String stTag = "<table";
		String edTag = "</table>";

		StringBuffer tablesBuf = new StringBuffer();

		// table count
		for (count = 0; true; count++) {
			if (count > 0) {
				strIndex = html.indexOf(stTag, strIndex + stTag.length());
			} else {
				strIndex = html.indexOf(stTag, strIndex);
			}
			endIndex = html.indexOf(edTag, strIndex);

			if (strIndex == -1 || endIndex == -1)
				break;

			// if(count > 0) tablesBuf.append("\n\n<table><tr><td nowrap height='5'></td></tr></table>");
			if (count > 0)
				tablesBuf.append("\n\n<p>");
			tablesBuf.append((html.substring(strIndex, endIndex + edTag.length())).toString());
		}

		return tablesBuf.toString();
	}

	// html의 tag만 소문자료 변경
	public static String toLowerCase(String html) {
		if (MString.isNull(html))
			return html;
		return toLowerCase(new StringBuffer(html));
	}

	public static String toLowerCase(StringBuffer htmlBuff) {
		String startStr = "<";
		String endStr = ">";
		int startIndex = -1;
		int endIndex = -1;
		String tag = "";

		while (true) {
			startIndex = htmlBuff.indexOf(startStr, endIndex);
			if (startIndex == -1)
				break;

			endIndex = htmlBuff.indexOf(endStr, startIndex);
			if (endIndex == -1)
				break;

			tag = htmlBuff.substring(startIndex, endIndex).toLowerCase();
			htmlBuff.delete(startIndex, endIndex);
			htmlBuff.insert(startIndex, tag);
		}

		return htmlBuff.toString();
	}

	// ////////////////////////// HTML 규칙 준수 여부 판탄및 부족한 TAG 자동 추가 ////////////////////////////
	// 1) <table> 와 </table>
	public static String addTABLE(String form) {
		return addTABLE(new StringBuffer(form));
	}

	public static String addTABLE(StringBuffer form) {

		// ban lower case form = form.toLowerCase();

		String strTag = "<table";
		String strTag2 = "<tbody>";
		String strTag3 = "<tr>";
		String endTag = "</table>";

		String inTag = "<table cellspacing=0 cellpadding=0 width='100%' border='1'>\n";

		int strIndex = form.indexOf(strTag);
		int strIndex2 = form.indexOf(strTag2);
		int strIndex3 = form.indexOf(strTag3);
		int endIndex = form.indexOf(endTag);

		if (strIndex < 0 || endIndex < strIndex) {
			if (strIndex2 >= 0 && strIndex2 < endIndex) {
				form = form.insert(strIndex2, inTag);
			} else if (strIndex3 >= 0 && strIndex3 < endIndex) {
				form = form.insert(strIndex3, inTag);
			}
		}

		return form.toString();
	}

	// 2) 한글 97 <table>다음에 <tr>이 없음, 그리고 </tr>이 없음 자동 추가 해줌
	public static String addTR(String form) {
		// form = form.toLowerCase();
		return addOpenTR(form);
	}

	public static String addTR(StringBuffer form) {
		return addOpenTR(form);
	}

	// 2-1) 한글 97 <table>다음의 <tr>이 없음 그래서 <tr>추가
	private static String addOpenTR(String form) {
		return addOpenTR(new StringBuffer(form));
	}

	private static String addOpenTR(StringBuffer form) {

		String stTABLE = "<table";
		String stTR = "<tr";
		String stTD = "<td";

		String inTR = "<tr>\n";
		int stTABLEIndex = -1;
		int stTRIndex = -1;
		int stTDIndex = -1;

		while (true) {
			stTABLEIndex = form.indexOf(stTABLE, stTABLEIndex);
			stTRIndex = form.indexOf(stTR, stTABLEIndex);
			stTDIndex = form.indexOf(stTD, stTABLEIndex);

			if (stTABLEIndex == -1 || stTRIndex == -1)
				break; // 양식으로서 정상적이지 못함
			if (stTABLEIndex > -1 && (stTRIndex > stTDIndex)) {
				form.insert(stTDIndex, inTR);
			}

			stTABLEIndex += stTABLE.length();
		}

		return addCloseTR(form);
	}

	private static String addCloseTR(StringBuffer form) {

		String stTR = "<tr>";
		String edTD = "</td>";
		String edTABLE = "</table>";

		String inTR = "</tr>\n";
		int stTRIndex = -1;
		int nextTRIndex = -1;
		int edTDIndex = -1;
		int edTABLEIndex = -1;

		while (true) {
			stTRIndex = form.indexOf(stTR, stTRIndex);
			nextTRIndex = form.indexOf(stTR, stTRIndex + stTR.length());
			edTABLEIndex = form.indexOf(edTABLE, stTRIndex);
			edTDIndex = form.indexOf(edTD, stTRIndex);
			if (stTRIndex == -1)
				break;

			if (stTRIndex > -1 && edTDIndex > -1 && nextTRIndex > 0) {
				form.insert(nextTRIndex, inTR);
				stTRIndex = nextTRIndex;
			} else if (stTRIndex > -1 && edTDIndex > -1 && nextTRIndex == -1 && edTABLEIndex > stTRIndex) {
				form.insert(edTABLEIndex, inTR);
				stTRIndex = edTABLEIndex;
			}
		}
		return form.toString();
	}

	public static String toHtml(String str) {
		CharArrayReader chr;
		BufferedReader inDesc;
		String line;
		String newDesc = "";

		try {
			// detalDesc를 보기 좋게 변경
			chr = new CharArrayReader(str.toCharArray());
			inDesc = new BufferedReader(chr);
                        
                        //v2 36.경쟁조건 : 검사시점과 사용시점 (File)_CWE-367 : Update by YOUNGJUN,CHO
			/*
                        line = inDesc.readLine();
			while (line != null) {
				newDesc += "<p>" + line + "</p>";
				line = inDesc.readLine();
			}
                        */
			while ((line = inDesc.readLine()) != null) {
				newDesc += "<p>" + line + "</p>";
			}
                        //================================================
                        
			str = newDesc;
			inDesc.close();
			return str;
		} catch (IOException ex) {
			System.err.println("error message : " + ex);
			return str;
		}
	}
}
