package net.woodyfolsom.cs6601.p3.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.stereotype.Repository;

import net.woodyfolsom.cs6601.p3.domain.Headline;

@Repository
public class HeadlineDaoImpl implements HeadlineDao {
	private static final String COUNT_ALL_QRY = "SELECT COUNT(1) FROM headlines";
	private static final String COUNT_DATASET_QRY = "SELECT COUNT(1) FROM headlines where dataset = ?";
	
	private static final String DELETE_BY_ID_STMT = "DELETE from headlines WHERE id = ?";
	
	private static final String INSERT_STMT = "INSERT INTO headlines (text, date, stock, dataset) values (?, ?, ?, ?)";
	
	private static final String SELECT_BY_ID_QRY = "SELECT * from headlines WHERE id = ?";
	private static final String SELECT_BY_STOCK_QRY = "SELECT * from headlines WHERE stock = ? AND date = ? AND dataset = 1";
	private static final String SELECT_BY_DATE_RANGE_QRY = "SELECT * from headlines WHERE stock = ? AND date >= ? AND date <= ? AND dataset = ?";
	
	private static final String ASSIGN_RANDOM_PCT_QRY = "update headlines set dataset = (select FLOOR(RAND() * (200 - 101) + 101))";
	private static final String REMAP_TRAINING_QRY = "update headlines set dataset = 1 where dataset >= 101 and dataset <= (100 + ?)";
	//private static final String REMAP_TEST_QRY = "update headlines set dataset = 2 where dataset >= (100 + ?) and dataset <= (100 + ?)";
	private static final String REMAP_VAL_QRY = "update headlines set dataset = 3 where dataset > (100 + ?) and dataset <= 200";
	
	private JdbcTemplate jdbcTemplate;
	
	@Override
	public boolean assignRandomDatasets(int training/*, int test*/, int validation) {
		if (training /*+ test*/ + validation != 100) {
			return false;
		}
		jdbcTemplate.update(ASSIGN_RANDOM_PCT_QRY);
		jdbcTemplate.update(REMAP_TRAINING_QRY,training);
		//jdbcTemplate.update(REMAP_TEST_QRY,training,training+test);
		jdbcTemplate.update(REMAP_VAL_QRY,training/*+test*/);
		return true;
	}
	
	public int deleteById(int headlineId) {
		return jdbcTemplate.update(DELETE_BY_ID_STMT,
				new RequestMapper(), headlineId);
	}
	
	public int insert(Headline headline) {
		return jdbcTemplate.update(INSERT_STMT, headline.getText(), headline.getDate(), headline.getStock(), headline.getDataset());
	}
	
	public int[] insertBatch(final List<Headline> headlines){
		 
		  return jdbcTemplate.batchUpdate(INSERT_STMT, new BatchPreparedStatementSetter() {
		 
			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				Headline headline = headlines.get(i);
				ps.setString(1, headline.getText());
				ps.setDate(2, new java.sql.Date(headline.getDate().getTime()));
				ps.setString(3, headline.getStock() );
				ps.setInt(4, headline.getDataset() );
			}
		 
			@Override
			public int getBatchSize() {
				return headlines.size();
			}
		  });
		}
	
	public Headline select(int headlineId) {
		return jdbcTemplate.queryForObject(SELECT_BY_ID_QRY,
				new RequestMapper(), headlineId);
	}
	
	public List<Headline> select(String stock, Date date) {
		return jdbcTemplate.query(SELECT_BY_STOCK_QRY,
				new RequestMapper(), stock, date, 1);
	}
	
	public List<Headline> select(String stock, Date startDate, Date endDate, int dataset) {
		return jdbcTemplate.query(SELECT_BY_DATE_RANGE_QRY,
				new RequestMapper(), stock, startDate, endDate, dataset);
	}
	
	@Autowired
	public void createTemplate(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	private class RequestMapper implements ParameterizedRowMapper<Headline> {

		@Override
		public Headline mapRow(ResultSet rs, int arg1) throws SQLException {
			Headline headline = new Headline();
			headline.setId(rs.getInt("id"));
			headline.setText(rs.getString("text"));
			headline.setStock(rs.getString("stock"));
			headline.setDate(rs.getDate("date"));
			headline.setDataset(rs.getInt("dataset"));
			return headline;
		}

	}

	@Override
	public int getCount() {
		return jdbcTemplate.queryForInt(COUNT_ALL_QRY);
	}

	@Override
	public int getCount(int dataset) {
		return jdbcTemplate.queryForInt(COUNT_DATASET_QRY,dataset);
	}
}