package com.fp.hbm.bgenerator;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import com.fp.common.exception.APPException;
import com.fp.persistence.commondb.exception.CommondbException;
import com.fp.hbm.helper.PersistenceHelperHQL;
import com.fp.hbm.persistence.TgeneFields;
import com.fp.hbm.persistence.TgeneFieldsKey;

public abstract class AbstractColumn {
	protected AbstractMapper mapper;
	protected TgeneFields fiedBeanReference=null;
	protected String name;

	protected boolean nullable = true;

	protected boolean fk = false;

	protected String comments;

	protected String type;

	protected String table;

	protected String entityPackage;

	protected String pacBase;

	protected boolean pk = false;

	protected int pkOrder;

	protected int length;

	protected int precision;

	protected int scale;

	public int getLength() {
		return length;
	}

	public void setLength(Integer pLength) {
		length = (pLength == null) ? 0 : pLength;
	}

	public boolean isPk() {
		return pk;
	}

	public void setPk(boolean pPk) {
		this.pk = pPk;
		if (pk) {
			this.nullable = false;
		}
	}

	public int getPkOrder() {
		return pkOrder;
	}

	public void setPkOrder(int pPkOrder) {
		pkOrder = pPkOrder;
	}

	public int getPrecision() {
		return precision;
	}

	public void setPrecision(Integer pPrecision) {
		precision = (pPrecision == null) ? 0 : pPrecision;
	}

	public int getScale() {
		return scale;
	}

	public void setScale(Integer pScale) {
		scale = (pScale == null) ? 0 : pScale;
	}

	public String getEntityPackage() {
		return entityPackage;
	}

	public void setEntityPackage(String pEntityPackage) {
		entityPackage = pEntityPackage;
	}

	public String getPacBase() {
		return pacBase;
	}

	public void setPacBase(String pPacBase) {
		pacBase = pPacBase;
	}

	public String getTable() {
		return table;
	}

	public void setTable(String pTable) {
		table = pTable;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String pComments) {
		comments = pComments;
	}

	public boolean isFk() {
		return fk;
	}

	public void setFk(boolean pFk) {
		fk = pFk;
	}

	public String getName() {
		return name;
	}

	public void setName(String pName) throws CommondbException {
		name = pName;
        TgeneFieldsKey k=new TgeneFieldsKey(this.mapper.getEnt().getPk().getTname(),this.mapper.getEnt().getPk().getEntity(),name);
        this.fiedBeanReference=(TgeneFields) PersistenceHelperHQL.get(TgeneFields.class, k);
	}

	public boolean isNullable() {
		return nullable;
	}

	public void setNullable(boolean pNullable) {
		nullable = pNullable;
	}

	public String getType() {
		return type;
	}

	public void setType(String pType) {
		type = pType;
	}

	protected String getJavaDataType() throws APPException {
		String data = null;
		//Si es un clob se genera como string
		if (type.indexOf("VARCHAR")>-1 || type.indexOf("CLOB") >-1) {
			return "java.lang.String";
		}
		if (type.indexOf("DATE")>-1) {
			return "java.sql.Date"; 
		}
		if (type.indexOf("TIMESTAMP") >-1) {
			return "java.sql.Timestamp";
		}
		if (type.indexOf("NUMBER") >-1||type.indexOf("NUMERIC")>-1) {
			if (this.scale != 0) {
				return "java.math.BigDecimal";
			} else {
				if (paramResource == null) {
					paramResource = ResourceBundle.getBundle("cfg");
				}
				String versioncontrol=paramResource.getString("vesion.control.field").toUpperCase();
				if(this.name.compareToIgnoreCase(versioncontrol)==0){
					return "java.lang.Integer";
				}
				if(this.length>10){
					data = "java.lang.Long";
				}else{
					data = "java.lang.Integer";
				}
				return data;
			}
		}
		if (type.indexOf("CLOB") >-1) {
			return "java.sql.Clob";
		}
		if (type.indexOf("BLOB") >-1) {
			return "java.sql.Blob";
		}

		if (type.indexOf("CHAR") >-1) {
			return "java.lang.String";
		}
		if (data == null) {
			throw new APPException("HM000", "Tipo de SQL no considerado" + type);
		}
		return data;
	}

	public String getJavaSimple() throws APPException {
		String data = null;
		//Si es un clob se gera como string
		if (type.indexOf("VARCHAR") >-1 || type.indexOf("CLOB") >-1) {
			return "String";
		}
		if (type.indexOf("DATE") >-1) {
			return "Date";  
		}
		if (type.indexOf("TIMESTAMP") >-1) {
			return "Timestamp";
		}
		if (type.indexOf("NUMBER") >-1||type.indexOf("NUMERIC") >-1) {
			if (this.scale != 0) {
				return "BigDecimal";
			} else {
				if(this.name.compareToIgnoreCase(paramResource.getString("vesion.control.field").toUpperCase())==0){
					return "Integer";
				}
				if(this.length<11){
					return "Integer";
				}

				return "Long";
			}
		}
		if (type.indexOf("CLOB") >-1) {
			return "Clob";
		}
		if (type.indexOf("BLOB") >-1) {
			return "Blob";
		}
		if (type.compareTo("CHAR") >-1) {
			return "String";
		}
		if (data == null) {
			throw new APPException("HM000", "Tipo de SQL no considerado" + type);
		}
		return data;
	}

	public String getGetName() {
		return "get" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + "()";
	}

	public void formatJavaDocParam(PrintWriter pw) {
		pw.println("@param p" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + " " + this.comments);

	}

	public void formatAsign(PrintWriter pw) {
		pw.println(" " + this.name + "=p" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + ";");

	}

	public String getParameterFormat() throws APPException {
		String data = "";
		data = this.getJavaSimple() + " p" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase();

		return data;
	}

	public List<String> getImportData() throws APPException {
		List<String> importData = new ArrayList<String>();
		String dt = this.getJavaDataType();
		if (dt.indexOf("java.lang") < 0) {
			importData.add(dt);
		}

		return importData;
	}

	private static ResourceBundle paramResource = null;

	public String formatJavaGetSet(boolean isPK) throws APPException {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		name = name.toLowerCase();
		pw.println("/**Obtiene el valor de " + this.getName());
		pw.println("@return valor de " + this.getName() + "*/");
		pw.println("public " + getJavaSimple() + " " + this.getGetName() + "{");
		pw.println("  return " + this.name + ";");
		pw.println("}");
		pw.println("/**Fija el valor de " + this.getName());
		pw.println("@param p" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + " nuevo Valor de " + this.getName()
				+ "*/");
		pw.println("public void set" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1) + "(" + getJavaSimple() + " p"
				+ this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + "){");
		if (!isPK) {
			if (paramResource == null)
				paramResource = ResourceBundle.getBundle("cfg");
			if (paramResource.getString("modify.manage").compareToIgnoreCase("true") == 0) {
				pw.println("  pcs.firePropertyChange(\"" + name + "\", " + name + ", p" + this.name.substring(0, 1).toUpperCase()
						+ this.name.substring(1).toLowerCase() + ");");
			}
		}
		pw.println("  " + this.name + "=p" + this.name.substring(0, 1).toUpperCase() + this.name.substring(1).toLowerCase() + ";");
		pw.println("}");

		String data = sw.toString();
		pw.close();
		return data;
	}

	public abstract String formatJava() throws APPException;

	public abstract String formatProperty() throws APPException;

	public abstract String formatComposeKey() throws APPException;

	public abstract void formatSinglePK(PrintWriter pw) throws APPException;

	public void formatHash(PrintWriter pw) {
		String getName = this.getGetName();
		pw.println("    result = result * 37 + (this." + getName + " == null ? 0 : this." + getName + ".hashCode());");

	}

	public void formatCompare(PrintWriter pw) {
		String getName = this.getGetName();
		pw.println("  if (this." + getName + " == null || that." + getName + " == null){");
		pw.println("      return false;");
		pw.println("  }");
		pw.println("  if (! this." + getName + ".equals(that." + getName + ")){");
		pw.println("    return false;");
		pw.println("  }");

	}

	public AbstractMapper getMapper() {
		return mapper;
	}

	public void setMapper(AbstractMapper mapper) {
		this.mapper = mapper;
	}
}
