package com.fitbank.homebanking;

import java.util.Iterator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.fitbank.common.crypto.Decrypt;
import com.fitbank.common.properties.PropertiesHandler;
import com.fitbank.dto.GeneralResponse;
import com.fitbank.dto.management.Criterion;
import com.fitbank.dto.management.Detail;
import com.fitbank.dto.management.Field;
import com.fitbank.dto.management.Record;
import com.fitbank.dto.management.Table;

public class Search {

	public static final String PARAM_QUERY = "_query";
	public static PropertiesHandler jsonProp=null;

	private HttpServletRequest request;

	private HttpSession session;

	private DataManage dm;

	private String query;
	
	private String security;

	public Search(HttpServletRequest pRequest) throws Exception {
		this.request = pRequest;
		this.session = this.request.getSession();
		dm = (DataManage) session.getAttribute("dm");		
		query = this.request.getParameter(PARAM_QUERY);
		if(jsonProp==null){
			jsonProp=new PropertiesHandler("json");
		}
	}

	private Detail prepareDetail() throws Exception {
		Detail det = new Detail();
	this.security=jsonProp.getStringValue("json."+this.query+".security");
		try {
			if(this.security==null||security.compareTo("false")!=0){
			  dm.prepareHeaderData(det);
			}else{
			this.prepareHeaderDataWithoutLogIn(det);
			}
		} catch (Exception e) {
			throw new Exception("EL USUARIO NO ESTA INGRESADO ", e);
		}
		det.setType(MessageTypes.CON.name());
		det.setSubsystem("00");
		det.setTransaction("0003");
		det.setVersion("00");
		this.prepareTable(det);
		return det;
	}

	private void prepareHeaderDataWithoutLogIn(Detail pDetail)throws Exception{
		pDetail.setUser(jsonProp.getStringValue("json.user"));
        Decrypt de = new Decrypt();
        if (!de.isWebencrypt()) {
            pDetail.setPassword(de.encrypt(jsonProp.getStringValue("json.password")));
        }
        pDetail.setIpaddress("0.0.0.0");
        pDetail.setSessionid(jsonProp.getStringValue("json.sessionId"));
        pDetail.setLanguage(jsonProp.getStringValue("json.language"));
        pDetail.setTerminal(jsonProp.getStringValue("json.terminal"));
        pDetail.setChannel(jsonProp.getStringValue("json.channel"));
        pDetail.setRole(jsonProp.getIntValue("json.rol"));
        pDetail.setCompany(jsonProp.getIntValue("json.company"));
        pDetail.setOriginbranch(jsonProp.getIntValue("json.originbranch"));
        pDetail.setOriginoffice(jsonProp.getIntValue("json.originoffice"));
        pDetail.setSecuritylevel(jsonProp.getIntValue("json.securitylevel"));
        pDetail.setAccountingdate(new java.sql.Date(System.currentTimeMillis()));
        pDetail.findFieldByNameCreate("_AUTOLOTE").setValue("1");
	}
	
	
	private void prepareTable(Detail pDet) throws Exception {
		if (query == null) {
			throw new Exception("Consulta no definida");
		}
		if (query.compareTo("trnfrq") == 0) {
			commonTransactions(pDet, null);
			return;
		}
		if (query.compareTo("trndet") == 0) {
			String name = request.getParameter("_name");
			if (name == null) {
				throw new Exception("Nombre no definido");
			}
			commonTransactions(pDet, name);
			return;
		}
		if(this.jsonQuery(pDet, query)){
			return;
		}
		throw new Exception("Consulta " + query + " no implementada");
	}
  private boolean jsonQuery(Detail pDetail, String pName) throws Exception{
  	String tableData=jsonProp.getStringValue("json."+pName+".table");
  	if(tableData==null){
  		return false;
  	}
  	Table table=new Table(tableData);
  	table.setAlias(this.query);
  	pDetail.addTable(table);
  	for (Criterion cri : table.getCriteria()) {
			String val= this.request.getParameter(cri.getName());
			if(val==null){
				continue;
			}
			cri.setValue(val);
		}
  	return true;
  }
  private String data="";
  private boolean jsonQueryData(Detail pDetail) throws Exception{
  	String tableId=jsonProp.getStringValue("json."+this.query+".id");
  	if(tableId==null){
  		return false;
  	}
  	Table table=pDetail.findTableByAlias(this.query);
  	if(table.getRecordCount()<=0){
  		return true;
  	}
  	this.data=this.formatDataFinal(table.getRecords(), tableId,null);
  	return true;
  }
	private void commonTransactions(Detail pDet, String pName) throws Exception {
		Table tbl = new Table("TMOVIMIENTOSFRECUENTES", "trnfrq");
		Criterion caux = new Criterion("CUSUARIO", pDet.getUser());
		tbl.addCriterion(caux);
		String aux = request.getParameter("CSUBSISTEMA");
		if (aux == null) {
			throw new Exception("Subsistema no definido");
		}
		caux = new Criterion("CSUBSISTEMA", aux);
		tbl.addCriterion(caux);
		aux = request.getParameter("CTRANSACCION");
		if (aux == null) {
			throw new Exception("Transacción no definida");
		}
		caux = new Criterion("CTRANSACCION", aux);
		tbl.addCriterion(caux);
		aux = request.getParameter("VERSIONTRANSACCION");
		if (aux == null) {
			throw new Exception("Version no definida");
		}
		caux = new Criterion("VERSIONTRANSACCION", aux);
		tbl.addCriterion(caux);
		if (pName != null) {
			caux = new Criterion("NOMBRETRANSACCION", pName);
			tbl.addCriterion(caux);
		}
		Record rec = new Record();
		if (pName != null) {
			rec.findFieldByNameCreate("DATOS");
		} else {
			rec.findFieldByNameCreate("NOMBRETRANSACCION");
		}
		tbl.addRecord(rec);
		pDet.addTable(tbl);
	}

	public String executeQuery() throws Exception {
		Detail det = this.prepareDetail();
		BussinessDelegate bd = new BussinessDelegate();
		det = bd.process(det);
		return this.manageResponse(det);
	}

	private String manageResponse(Detail pDet) throws Exception {
		if (pDet.getResponse().getCode().compareTo(GeneralResponse.OK) != 0) {
			return pDet.getResponse().getUserMessage();
		}
		if (query.compareTo("trnfrq") == 0) {
			return this.formatData(pDet.findTableByAlias("trnfrq").getRecords(), "NOMBRETRANSACCION");
		}
		if (query.compareTo("trndet") == 0) {
			Iterator<Record> trndet = pDet.findTableByAlias("trnfrq").getRecords().iterator();
			if (trndet.hasNext()) {
				Record rec = trndet.next();
				Object value = rec.findFieldByNameCreate("DATOS").getValue();
				if (value == null) {
					throw new Exception("Información no encontrada");
				}
				return value.toString();
			} else {
				throw new Exception("Información no encontrada");
			}
		}
		if(this.jsonQueryData(pDet)){
			return this.data;
		}
		throw new Exception("Consulta " + query + " no implementada");
	}
	
	private String formatData(Iterable<Record> pData, String pId, String... pFields) {
		return formatDataFinal( pData, pId,  pFields);
	}
	private String formatDataFinal(Iterable<Record> pData, String pId, String[] pFields) {

		String data = "{identifier:\"" + pId + "\",";
		data += "items: [";
		boolean first = true;
		for (Record record : pData) {
			if (first) {
				first = false;
			} else {
				data += ",";
			}
			data += "{";
			data += pId + ":'" + record.findFieldByNameCreate(pId).getValue() + "'";
			if (pFields != null) {
				for (String field : pFields) {
					data += "," + field + ":'" + record.findFieldByNameCreate(field).getValue() + "'";
				}
			}else{
				for (Field field : record.getFields()) {
					String fname=field.getRealName();
					fname=fname.replace('.', '_');
					fname=fname.replace('+', '_');
					if(fname.compareTo(pId)==0){
						continue;
					}
					data += "," + fname + ":'" + field.getValue() + "'";
				}
			}
			data += "}";
		}
		return data + "]}";
	}
}
