package com.fitbank.web;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import com.fitbank.common.exception.FitbankException;
import com.fitbank.common.helper.FormatDates;
import com.fitbank.common.logger.FitbankLogger;
import com.fitbank.dto.GeneralResponse;
import com.fitbank.dto.management.Detail;
import com.fitbank.dto.management.Field;
import com.fitbank.dto.management.Record;

public class LOV {
	private HttpServletRequest request;

	private String lovName;

	private int page = 1;

	private Map<String, String> parameters = new HashMap<String, String>();

	private Detail detail = null;

	private List<String> columns = new ArrayList<String>();

	private List<String> columnLabels = new ArrayList<String>();
	private List<String> columnAlign = new ArrayList<String>();
	private List<String> columnCriteria = new ArrayList<String>();
	private List<String> columnDataType = new ArrayList<String>();
	private List<String> columnFormat = new ArrayList<String>();

	private List<Integer> columnWidth = new ArrayList<Integer>();

	public static final String LOV_NAME = "_lov_";

	public static final String LOV_PAGE = "_page_";

	public static final String LOV_TITLE_CTL = "LOV_TITLE";

	public static final String LOV_COLUMNS_CTL = "LOV_COLUMNS";

	public static final String LOV_COLUMN_LABELS_CTL = "LOV_COLUMN_LABELS";

	public static final String LOV_COLUMN_WIDTH_CTL = "LOV_COLUMN_WIDTHS";
	public static final String LOV_COLUMN_ALIGN_CTL = "LOV_COLUMN_ALIGN";
	public static final String LOV_COLUMN_CRITERIA_CTL = "LOV_COLUMN_CRITERIA";
	public static final String LOV_COLUMN_FORMAT_CTL = "LOV_COLUMN_FORMAT";
	public static final String LOV_COLUMN_DATATYPE_CTL = "LOV_COLUMN_DATATYPE";

	public static final String LOV_CODE_CTL = "LOV_CODE";

	public static final String LOV_DATA_CTL = "LOV_DATA";

	public static final String VALUE_SEPARATOR = ";";
	private Map<String, String> hidden=new HashMap<String, String>();
	private String errorMsg="";
	private boolean error=false;
	private String url="";

	@SuppressWarnings("unchecked")
	public LOV(HttpServletRequest pRequest) throws Exception {
		request = pRequest;
		lovName = request.getParameter(LOV_NAME);
		if(lovName==null){
			throw new FitbankException("JSF001","LOV no definido");
		}
		FitbankLogger.getLogger().debug(lovName);
		String aux = request.getParameter(LOV_PAGE);
		if (aux != null) {
			page = Integer.parseInt(aux);
		}

		Enumeration<String> param = request.getParameterNames();
		while (param.hasMoreElements()) {
			String paramName = param.nextElement();
	
			
			if (paramName.indexOf("cLov_") < 0&&paramName.indexOf("pLov_") < 0) {
				continue;
			}
			String val = request.getParameter(paramName).trim();
			if(paramName.indexOf("cLov_") >= 0) {
				this.url+="&"+paramName+"="+val;
			}
			if (val.compareTo("_") == 0) {
				val = "";
			}
			
		//	paramName = paramName.replaceAll("cLov_", "");
			paramName = paramName.replaceAll("pLov_", "cLov_");
			parameters.put(paramName, val);
		}
		DataManage dm = (DataManage) request.getSession().getAttribute(DataManage.KEY);
		detail = new Detail();
		detail.setType(MessageTypes.CON.name());
		detail.setSubsystem("03");
		detail.setTransaction("7003");
		detail.setVersion("01");
		dm.prepareHeaderData(detail,this.request);
		detail.findFieldByNameCreate("NAME").setValue(this.lovName);
		detail.findFieldByNameCreate("PAGE").setValue(this.page);
		for (String key : this.parameters.keySet()) {
			detail.findFieldByNameCreate(key).setValue(this.parameters.get(key));
		}

		BussinessDelegate bd = new BussinessDelegate();
		Transaction tt = (Transaction) request.getSession().getAttribute(DataManage.TRN_DATA);
		if (tt != null)
			detail.setRealtransaction(tt.getSubsystem() + ":" + tt.getTransaction());
		this.detail = bd.process(detail);
		if(this.detail.getResponse().getCode().compareTo(GeneralResponse.OK)!=0){
			this.error=true;
			this.errorMsg=this.detail.getResponse().getUserMessage();
		}else{
		 this.prepareColumns();
		}
	}

	public String getLOVData() throws Exception {
		try {
			if(this.error){
				return this.errorMsg;
			}
			String data = "";
			data += this.getHeader((String) detail.findFieldByName(LOV_TITLE_CTL).getValue());
			String alias = (String) detail.findFieldByName(LOV_DATA_CTL).getValue();
			data += this.getData(detail.findTableByAlias(alias).getRecords());
			String has=detail.findTableByAlias(alias).getHasMorePages();
			data += this.getFooter((has!=null&&has.compareTo("1")==0));
			return data;
		} catch (Exception e) {
			return e.getMessage();
		}
	}

	private String getHeader(String pTitle) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		pw.println("<form name='lov'>");
		pw.println("<script>");
		pw.println(" function executeQueryLov(url){");
		String par = "";
		for (String col : columns) {
			par += "+'&" + col + "='+document.forms['lov']." + col + ".value";
			if (parameters.containsKey(col)) {
				parameters.remove(col);
			}
		}
		String sParameters = "";
		for (String key : parameters.keySet()) {
			sParameters += "&" + key + "=" + parameters.get(key);
		}
		int total=0;
		for (int colW : this.columnWidth) {
			total+=colW;
		}
		
		pw.println(" queryLov(url+\"" + sParameters + "\" " + par + ");");
		pw.println("}");
	//	pw.println("resizeLov("+total+");");		
		pw.println("</script>");
		pw.println("  <table width='"+total+"'  class='simple'>");
		pw.println("  <tr><td colspan='" + this.columns.size() + "'>");
		pw.println(pTitle);
		pw.println("</td></tr>");
		pw.println(" <tr>");
		
		for (int i = 0; i < this.columnLabels.size(); i++) {
			String label = this.columnLabels.get(i);
			if (this.columnWidth.size() == this.columnLabels.size()) {
				int width=this.columnWidth.get(i);
				if(width==0){
					hidden.put(this.columns.get(i), "");
				}
				pw.println("  <th width='" + width + "'  >" +((width==0)?"": label) + "</th>");
			} else {
				pw.println("  <th  >" +label + "</th>");
			}
		}
		pw.println("</tr><tr>");
		int i=0;
		for (String col : columns) {
			String value = this.request.getParameter("cLov_" + col);
                        if(value == null){
                            value = this.request.getParameter("pLov_" + col);
                        }
			if (value == null || value.compareTo("_") == 0) {
				value = "";
			}
			if(hidden.containsKey(col) ||!showCriteria(i)){
				if(!showCriteria(i)){
					pw.println("<th   class='sortable' bgcolor='#eeeeee'></th>");
				}else{
				pw.println("<th   class='sortable'></th>");
				}
			}else{
                            pw.println("<th   class='sortable'><input  type='text' name='pLov_" + col + "' id='pLov_" + col + "' style='width:100%' value='" + value + "'/></th>");
			}
			i++;
		}
		pw.println("</tr>");
		pw.close();
		return sw.toString();
	}
	private boolean showCriteria(int pIndex) {
		try{
			return (this.columnCriteria.get(pIndex).compareTo("1")==0);
		}catch(Exception e){
			return true;
		}
	}
	private String getAlign(int pIndex,String pVal) {
		try{
			String align= this.columnAlign.get(pIndex);
			if(align.compareTo("NULL")==0){
				if(pVal.length()<4){
					 return "align='center'";
					}
				return "";
			}
				return "align='"+align+"'";
		}catch(Exception e){
			if(pVal.length()<4){
			 return "align='center'";
			}
			return "align='center'";
		}
	}
	private String getFooter(boolean hasMore) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		pw.println("<tr><td colspan='" + columns.size() + "'>");
		pw.println("<table width='100%'>");
		pw.println("<tr>");
		String prev = this.lovName+url + ((this.page == 1) ? "" : ("&_page_=" + (page - 1)));
		String next = this.lovName+url + "&_page_=" + (page + 1);
		pw.println(" <td width='30%'><input type='button'  "+((this.page == 1)?"disabled='true'":"")+"  name='previous' id='previous' value='Anterior' onclick=\"executeQueryLov('" + prev.replaceAll("'", "\\\\'") + "');return false\" /></td>");
		pw.println(" <td width='30%'><input type='button'  name='query' id='query' value='Consultar' onclick=\"executeQueryLov('" + (this.lovName+this.url).replaceAll("'", "\\\\'") + "');return false\" /></td>");
		pw.println(" <td width='30%'><input type='button'  name='next' "+((!hasMore)?"disabled='true'":"")+"  id='next' value='Siguiente' onclick=\"executeQueryLov('" + next.replaceAll("'", "\\\\'") + "');return false\"/></td>");
		pw.println(" </tr></table></td></tr></table></form>");
		pw.close();
		return sw.toString();
	}


	private String getData(Iterable<Record> pData) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		int row=0;
		for (Record record : pData) {
			row++;
			pw.println("   <tr  onmouseover=\"this.className='sel'\" onmouseout=\"this.className=''\" id='lovtr"+row+"'>");
			int index=-1;
			boolean first=true;
			for (String col : columns) {
				index++;
				Field f=record.findFieldByName(col);
				String value=this.manageValue(index,f.getValue());
				String style="style='";				
				if(this.hidden.containsKey(col)){
					style+="background-color:#FFFFFF; color:#FFFFFF;font-size: 1px;";
				}
				style+="'";
				String align=this.getAlign(index, value);
	
				if(f.getDatatype().compareTo("java.math.BigDecimal")==0){
					align="align='right'";
				}				
				if(first){
				first=false;
				pw.println("<td "+style+" "+align+"><a href='javascript:selectLovRecord($(\"lovtr"+row+"\"));' class='lovKey'  id='link"+row+"'>" + value + "</a></td>");
				}else{
					pw.println("<td "+style+" "+align+" onclick='selectLovRecord(this);'>" + value + "</td>");
				}
			}
			pw.println("   </tr>");
		}

		pw.close();
		return sw.toString();
	}
  private String manageValue(int index,Object pValue) {
  	String value="";
		if(pValue==null){
			return "";
		}
		String datatype="";
		String format="";
		try{
			datatype=columnDataType.get(index);
		}catch(Exception e){
			datatype="NULL";
		}
		try{
			format=columnFormat.get(index);
		}catch(Exception e){
			format="NULL";
		}
		if(datatype.compareTo("NULL")!=0&&datatype.length()==1){
			switch (datatype.charAt(0)) {
			case 'C':
				value=""+pValue;
				break;
			case 'N':
				BigDecimal bdVal=new BigDecimal(""+pValue);
				if(format.compareTo("NULL")==0){
				  value=""+bdVal.longValue();
				}else{
					DecimalFormat df=new DecimalFormat(format);
					value=df.format(bdVal.doubleValue());
				}
				break;
			case 'D':
				try{
				Date date=null;
				if(pValue instanceof String){
					 date=new Date( FormatDates.getInstance().getTransportDateFormat().parse(""+pValue).getTime());
				}
				if(pValue instanceof Date){
					 date=(Date)pValue;
				}
				if(format.compareTo("NULL")==0){
					if(pValue instanceof String){
						value=(String)pValue;
					}
				  value=""+date;
				}else{
					SimpleDateFormat df=new  SimpleDateFormat(format);
					value=df.format(date);
				}
				}catch(Exception e){
					value=""+pValue;
				}
				break;
			case 'T':
				try{
				Timestamp date=null;
				if(pValue instanceof String){
					 date=new Timestamp( FormatDates.getInstance().getTransportTimestampFormat().parse(""+pValue).getTime());
				}
				if(pValue instanceof Timestamp){
					 date=(Timestamp)pValue;;
				}
				if(format.compareTo("NULL")==0){
					if(pValue instanceof String){
						value=(String)pValue;
					}
				  value=""+date;
				}else{
					SimpleDateFormat df=new  SimpleDateFormat(format);
					value=df.format(date);
				}
				}catch(Exception e){
					value=""+pValue;
				}
				break;				
			default:
				value=""+pValue;
				break;
			}
		}
		else{
		if(pValue instanceof BigDecimal){
			DecimalFormat df=new DecimalFormat("###,###,###,###,##0.00");
			value=df.format(((BigDecimal)pValue).doubleValue());
		}else{
			value=""+pValue;
		}
		}
  	return value;
  }
	private void prepareColumns() throws Exception {
		String data = (String) this.detail.findFieldByName(LOV_COLUMNS_CTL).getValue();
		if (data == null || data.compareTo("") == 0) {
			throw new Exception("Lista de valores no Tiene Columnas Definidas");
		}
		this.columns = new ArrayList<String>();
		StringTokenizer st = new StringTokenizer(data, ";");
		while (st.hasMoreElements()) {
			this.columns.add((String) st.nextElement());
		}
		data = (String) this.detail.findFieldByName(LOV_COLUMN_LABELS_CTL).getValue();
		if (data == null || data.compareTo("") == 0) {
			throw new Exception("Lista de valores no Tiene Columnas Definidas");
		}
		this.columnLabels = new ArrayList<String>();
		st = new StringTokenizer(data, ";");
		while (st.hasMoreElements()) {
			this.columnLabels.add((String) st.nextElement());
		}
		if (this.columnLabels.size() != this.columns.size()) {
			throw new Exception("El nï¿½mero de elementos en la Lista de columnas y etiquetas no son iguales");
		}

		data = (String) this.detail.findFieldByName(LOV_COLUMN_WIDTH_CTL).getValue();
		if (!(data == null || data.compareTo("") == 0)) {
			this.columnWidth = new ArrayList<Integer>();
			st = new StringTokenizer(data, ";");
			while (st.hasMoreElements()) {
				this.columnWidth.add(Integer.parseInt((String) st.nextElement()));
			}
			if (this.columnWidth.size() != this.columns.size()) {
				this.columnWidth = new ArrayList<Integer>();
			}
		}

		data = (String) this.detail.findFieldByNameCreate(LOV_COLUMN_ALIGN_CTL).getValue();
		if (!(data == null || data.compareTo("") == 0)) {
			this.columnAlign = new ArrayList<String>();
			st = new StringTokenizer(data, ";");
			while (st.hasMoreElements()) {
				this.columnAlign.add((String) st.nextElement());
			}
			if (this.columnAlign.size() != this.columns.size()) {
				this.columnAlign = new ArrayList<String>();
			}
		}
		
		data = (String) this.detail.findFieldByNameCreate(LOV_COLUMN_CRITERIA_CTL).getValue();
		if (!(data == null || data.compareTo("") == 0)) {
			this.columnCriteria = new ArrayList<String>();
			st = new StringTokenizer(data, ";");
			while (st.hasMoreElements()) {
				this.columnCriteria.add((String) st.nextElement());
			}
			if (this.columnCriteria.size() != this.columns.size()) {
				this.columnCriteria = new ArrayList<String>();
			}
		}
		
		data = (String) this.detail.findFieldByNameCreate(LOV_COLUMN_FORMAT_CTL).getValue();
		if (!(data == null || data.compareTo("") == 0)) {
			this.columnFormat = new ArrayList<String>();
			st = new StringTokenizer(data, ";");
			while (st.hasMoreElements()) {
				this.columnFormat.add((String) st.nextElement());
			}
			if (this.columnFormat.size() != this.columns.size()) {
				this.columnFormat = new ArrayList<String>();
			}
		}
		
		data = (String) this.detail.findFieldByNameCreate(LOV_COLUMN_DATATYPE_CTL).getValue();
		if (!(data == null || data.compareTo("") == 0)) {
			this.columnDataType = new ArrayList<String>();
			st = new StringTokenizer(data, ";");
			while (st.hasMoreElements()) {
				this.columnDataType.add((String) st.nextElement());
			}
			if (this.columnDataType.size() != this.columns.size()) {
				this.columnDataType = new ArrayList<String>();
			}
		}
		
	}
}