/******************************************************************************
*
* Copyright: Intellectual Property of Four Elements Capital Pte Ltd, Singapore.
* All rights reserved.
*
******************************************************************************/

package com.fourelementscapital.db.mariadb;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import com.fourelementscapital.db.ContractDB;
import com.fourelementscapital.db.GeneralUtilDB;
import com.fourelementscapital.db.vo.Contract;
import com.fourelementscapital.db.vo.Strategy;

/**
 * Contract MySQL DAO implementation
 */
public class ContractDBMariaDB extends ContractDB {
	
private Logger log=LogManager.getLogger(ContractDB.class.getName());
	
	private String tablename;
	
 
	/**
	 * Constructor
	 * @param tablename table name
	 */ 
	public ContractDBMariaDB(String tablename){
		this.tablename=tablename;
	}
	
	/**
	 * Constructor
	 */ 
	public ContractDBMariaDB(){
	}	

 
	/**
	 * {@inheritDoc}
	 */	
	public void updateRecords(Connection con,Vector records) throws Exception {
		
		PreparedStatement st=con.prepareStatement("INSERT into "+this.tablename+" (cdate,contract,val) VALUES(?,?,?) ");
		PreparedStatement st1=con.prepareStatement("SELECT cdate FROM "+this.tablename+" WHERE cdate=? AND contract=?");
		PreparedStatement st2=con.prepareStatement("UPDATE "+this.tablename+" SET val=? WHERE cdate=? AND contract=?");
		
		log.debug("records: size:"+records.size());
		for(Iterator<Contract> i=records.iterator();i.hasNext();){
			
			Contract contract=i.next();
			log.debug("contract: date():"+contract.getCdate());
			
			st1.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
			st1.setString(2, contract.getName());
			if(!st1.executeQuery().next()){
				st.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
				st.setString(2, contract.getName());
				st.setDouble(3, contract.getValue());
				st.executeUpdate();
			}else{
				st2.setDouble(1, contract.getValue());
				st2.setDate(2,  new java.sql.Date(contract.getCdate().getTime()));
				st2.setString(3,   contract.getName());
				st2.executeUpdate();
			}
		}
		st1.close();
		st2.close();
		st.close();
	}
	
	
	/**
	 * {@inheritDoc}
	 */			
	public void addRecords(Connection con,Vector records) throws Exception {
		log.debug("records: size:"+records.size());
		PreparedStatement st=con.prepareStatement("INSERT into "+this.tablename+"(cdate,contract,val) VALUES(?,?,?) ");		
		for(Iterator<Contract> i=records.iterator();i.hasNext();){
				Contract contract=i.next();
				log.debug("contract: date():"+contract.getCdate());
				log.debug("contract: sqldbs():"+new java.sql.Date(contract.getCdate().getTime()));
				log.debug("contract: this.tablename():"+this.tablename);
				
				st.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
				st.setString(2, contract.getName());
				st.setDouble(3, contract.getValue());
				st.executeUpdate();
		}
		st.close();
	}
	
	
	/**
	 * {@inheritDoc}
	 */		
	public void createTable(Connection con, int decimalpoint) throws Exception {
		
		String query="CREATE TABLE IF NOT EXISTS "+this.tablename +" ( ";
		query+="cdate datetime NOT NULL ,";
		query+="contract varchar(50), ";
		query+="val numeric(20,"+decimalpoint+")  ";
		query+=") ";
		 
		//System.out.println("ContractDB.class: query:"+query);
		 
		Statement st=con.createStatement();
		st.execute(query);
		st.close();
	}
	
	
	/*
	 * implemented but that of changing to different field.
	public void createNewContract(Connection con,String subtablename, String contract) throws Exception {
		
		String query="IF NOT EXISTS (select * from sysobjects where id = object_id('asset_contracts') and OBJECTPROPERTY(id, 'IsUserTable') = 1) ";
		query+="BEGIN ";
		query+="CREATE TABLE asset_contracts ( ";
		query+="tablename varchar(50) ,";
		query+="contract varchar(50) ";		
		query+=") ";
		query+="END ";
		 
		Statement st=con.createStatement();
		st.execute(query);
		st.close();
		
		PreparedStatement st1=con.prepareStatement("INSERT into asset_contracts(tablename,contract) VALUES(?,?) ");		
		st1.setString(1,subtablename);
		st1.setString(2, contract);
		st1.executeUpdate();
		st1.close();
		
	}
	

	public List getCustomContracts(Connection con,String subtablename) throws Exception {
		
		String query="select * from sysobjects where id = object_id('asset_contracts') and OBJECTPROPERTY(id, 'IsUserTable') = 1  ";
		
		Vector rtn=new Vector();
		Statement st=con.createStatement();
		ResultSet rs=st.executeQuery(query);
		if(rs.next()){
			Statement st1=con.createStatement();
			ResultSet rs1=st1.executeQuery("select contract from asset_contracts WHERE tablename='"+subtablename+"'");
			while(rs1.next()){
				rtn.add(rs.getString("contract"));
			}
			rs1.close();
			st1.close();
		}
		rs.close();
		st.close();
		return rtn;
		
	}

	*/
	
	
	/**
	 * {@inheritDoc}
	 */			
	public void updateSValRecords(Connection con,Vector records) throws Exception {
		PreparedStatement st=con.prepareStatement("INSERT into "+this.tablename+"(cdate,contract,val,sval) VALUES(?,?,?,?) ");
		PreparedStatement st1=con.prepareStatement("SELECT cdate FROM "+this.tablename+" WHERE cdate=? AND contract=?");
		PreparedStatement st2=con.prepareStatement("UPDATE "+this.tablename+" SET val=?,sval=? WHERE cdate=? AND contract=?");
		for(Iterator<Strategy> i=records.iterator();i.hasNext();){
			
			Strategy contract=i.next();
			st1.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
			st1.setString(2, contract.getName());
			if(!st1.executeQuery().next()){
				st.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
				st.setString(2, contract.getName());
				if(contract.getSvalue()!=null){
					st.setObject(3, null);
				}else{
					st.setDouble(3, contract.getValue());
				}
				st.setString(4, contract.getSvalue());
				st.executeUpdate();
			}else{
				if(contract.getSvalue()!=null){
					st2.setObject(1, null);
				}else{
					st2.setDouble(1, contract.getValue());
				}
				st2.setString(2, contract.getSvalue());
				st2.setDate(3,  new java.sql.Date(contract.getCdate().getTime()));				
				st2.setString(4,   contract.getName());				
				st2.executeUpdate();
			}
		}
		st1.close();
		st2.close();
		st.close();
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public void addSValRecords(Connection con,Vector records) throws Exception {
		PreparedStatement st=con.prepareStatement("INSERT into "+this.tablename+"(cdate,contract,sval) VALUES(?,?,?) ");		
		for(Iterator<Strategy> i=records.iterator();i.hasNext();){
				Strategy contract=i.next();
				st.setDate(1, new java.sql.Date(contract.getCdate().getTime()));
				st.setString(2, contract.getName());
				//st.setDouble(3, contract.getValue());
				st.setString(3, contract.getSvalue());
				st.executeUpdate();
		}
		st.close();		
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public void createSValTable(Connection con, int decimalpoint) throws Exception {
		
		String query="CREATE TABLE IF NOT EXISTS "+this.tablename +" ( ";
		query+="cdate datetime NOT NULL ,";
		query+="contract varchar(50), ";
		query+="sval varchar(50), ";
		query+="val numeric(20,"+decimalpoint+")  ";
		query+=") ";
		 
		//System.out.println("ContractDB.class: query:"+query);
		 
		Statement st=con.createStatement();
		st.execute(query);
		st.close();
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public int checkSValueField(Connection con) throws Exception {
		String query="select count(*) as cnum  from "+this.tablename+" where val is not null";
		Statement st=con.createStatement();
		ResultSet rs=st.executeQuery(query);
		int valcount=1;
		if(rs.next()){
			valcount=rs.getInt("cnum");
		}
		rs.close();
		st.close();
		return valcount;
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public int countRecords(Connection con) throws Exception {
		String query="select count(*) as cnum  from "+this.tablename+" ";
		Statement st=con.createStatement();
		ResultSet rs=st.executeQuery(query);
		int valcount=1;
		if(rs.next()){
			valcount=rs.getInt("cnum");
		}
		rs.close();
		st.close();
		return valcount;
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public boolean checkSValueFieldTypeExist(Connection con) throws Exception {
		String query="SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '"+this.tablename+"' AND COLUMN_NAME = 'sval' AND table_schema = '"+getDb()+"'";
		Statement st=con.createStatement();
		ResultSet rs=st.executeQuery(query);
	    boolean exist=false;
		if(rs.next()){
			exist=true;
		}
		return exist;
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public List getContractTitles(Connection con) throws Exception {
		Vector rtn=new Vector();
		Statement st=con.createStatement();
		ResultSet rs=st.executeQuery("SELECT distinct contract FROM "+this.tablename);
		while(rs.next()){
			rtn.add(rs.getString("contract"));
		}
		rs.close();
		st.close();
		return rtn;
	}

	
	/**
	 * {@inheritDoc}
	 */		
	public List getContractTitles(Connection con, String datequery) throws Exception {
		Vector rtn=new Vector();
		Statement st=con.createStatement();		 
		datequery=GeneralUtilDB.convertFromSQL(datequery);
		ResultSet rs=st.executeQuery("SELECT distinct contract FROM "+this.tablename+((datequery!=null && !datequery.equals(""))? "  WHERE "+datequery:""));
		while(rs.next()){
			rtn.add(rs.getString("contract"));
		}
		rs.close();
		st.close();
		return rtn;
	}


	/**
	 * {@inheritDoc}
	 */		
	public void updateMasterTable(Connection con,String mtable,String fieldname) throws Exception {
		
		String query="CREATE TABLE IF NOT EXISTS asset_master ( ";
		query+="commodity varchar(50) NOT NULL ,";
		query+="commodity_field varchar(100), ";
		query+="commodity_fieldoriginal varchar(100) ";
		query+=") ";
		 
		 
		Statement st=con.createStatement();
		st.execute(query);
		st.close();	
		
		PreparedStatement st1=con.prepareStatement("SELECT commodity FROM asset_master WHERE commodity=? AND commodity_field=?");
		PreparedStatement st2=con.prepareStatement("INSERT into asset_master(commodity,commodity_field,commodity_fieldoriginal) VALUES(?,?,?) ");

		st1.setString(1, mtable);
		st1.setString(2, this.tablename);
		if(!st1.executeQuery().next()){
			st2.setString(1, mtable);
			st2.setString(2, this.tablename);
			st2.setString(3, fieldname);			
			st2.executeUpdate();
		}		
		st1.close();
		st2.close();
	}
	
	
	/**
	 * {@inheritDoc}
	 */	
	public String generateSQLXLQueryPlainQuery(String fieldtable, int nmonths, List contractTitleList) {
		
		String rtn="SELECT cdate ";
		for(Iterator<String> it=contractTitleList.iterator();it.hasNext();){
			String contract=it.next();
			rtn+=",\r\nMAX(CASE WHEN contract='"+contract+"' THEN val END) AS "+contract+" ";
		}
		rtn+="\r\nFROM "+fieldtable+" WHERE cdate>=DATE_ADD(CURRENT_TIMESTAMP(), INTERVAL -" + nmonths + " month) GROUP BY cdate ORDER BY cdate DESC";
		return rtn;

	}	
	
}