package net.woodyfolsom.cs6601.p3;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.stereotype.Component;

import net.woodyfolsom.cs6601.p3.domain.Company;
import net.woodyfolsom.cs6601.p3.domain.Headline;
import net.woodyfolsom.cs6601.p3.domain.StockPrice;
import net.woodyfolsom.cs6601.p3.ngram.NGramModel;
import net.woodyfolsom.cs6601.p3.svc.HeadlineService;

@Component
public class PricePoller {
	private static final File stockSymbolsCSV = new File("stock_symbols.csv");

	private static final int INVALID_DATE = 1;
	private static final int IO_EXCEPTION = 2;
	private static final int STOCK_SYMBOL_CSV_NOT_FOUND = 3;

	@Autowired
	HeadlineService mySQLHeadlineServiceImpl;

	private NGramModel ngramModel = new NGramModel();
	
	public static void main(String... args) {

		ApplicationContext context = new FileSystemXmlApplicationContext(
				new String[] { "AppContext.xml" });
		PricePoller modelGenerator = context.getBean(PricePoller.class);
		DateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
		
		Date startDate = null;
		Date endDate = null;
		try {
			startDate = dateFmt.parse("2012-01-01");
			endDate = dateFmt.parse("2012-04-14");
		} catch (ParseException pe) {
			System.exit(INVALID_DATE);
		}
		
		List<Headline> trainingSet = new ArrayList<Headline>();
		//actually, this is the TEST dataset
		List<Headline> testSet = new ArrayList<Headline>();
		Map<String,Map<Date,StockPrice>> stockTrends = new HashMap<String,Map<Date,StockPrice>>();
		try {
			List<Company> fortune50 = modelGenerator
					.getFortune50(stockSymbolsCSV);
			for (Company company : fortune50) {
				stockTrends.put(company.getStockSymbol(), new HashMap<Date,StockPrice>());
				System.out.println("Polling price data for " + company.getName());
				File stockPriceFile = new File("data" + File.separator + company.getStockSymbol() + ".txt");
				BufferedReader buf;
				try {
					buf = new BufferedReader(new InputStreamReader(new FileInputStream(stockPriceFile)));
				} catch (FileNotFoundException fnfe) {
					System.out.println("Unable to find historical stock data file for: " + company.getStockSymbol());
					continue;
				} 
				String line;
				int linesRead = 0;
				try {
				while ((line = buf.readLine()) != null) {
					linesRead++;
					if (linesRead == 1) {
						continue; // header line
					}
					String[] fields = line.trim().split(",");
					Date date;
					try {
						date = dateFmt.parse(fields[0]);
					} catch (ParseException pe) {
						System.out.println("Error parsing date: " + fields[0]);
						continue;
					}
					if (date.compareTo(endDate) > 0) {
						continue;
					}
					if (date.compareTo(startDate) < 0) {
						break;
					}
					
					double open;
					double high;
					double low;
					double close;
					long volume;
					double adjClose;
					
					try {
						open = Double.parseDouble(fields[1]);
						high = Double.parseDouble(fields[2]);
						low = Double.parseDouble(fields[3]);
						close = Double.parseDouble(fields[4]);
						volume = Long.parseLong(fields[5]);
						adjClose = Double.parseDouble(fields[6]);
					} catch (NumberFormatException nfe) {
						System.out.println(nfe.getMessage());
						continue;
					}
					
					StockPrice stockPrice = new StockPrice(date,open,high,low,close,volume,adjClose);
					
					stockTrends.get(company.getStockSymbol()).put(date,stockPrice);
				}
				} catch (IOException ioe) {
					System.err.println(ioe.getMessage());
					continue;
				}
				try {
					buf.close();
				} catch (IOException ioe) {
					System.err.println(ioe.getMessage());
				}
			}
			for (Company company : fortune50) {
				System.out.println("Getting headlines for Fortune 50 company #"
						+ company.getId() + " (" + company.getName() + ")...");
				List<Headline> coTrainingSet = modelGenerator.mySQLHeadlineServiceImpl.getHeadlines(company.getStockSymbol(), startDate, endDate, 1);
				System.out.println("Pulled " + coTrainingSet.size() + " TRAINING headlines for "
						+ company.getStockSymbol() + " from " + startDate + " to " + endDate);
				List<Headline> coTestSet = modelGenerator.mySQLHeadlineServiceImpl.getHeadlines(company.getStockSymbol(), startDate, endDate, 3);
				System.out.println("Pulled " + coTestSet.size() + " VALIDATION headlines for "
						+ company.getStockSymbol() + " from " + startDate + " to " + endDate);
				
				trainingSet.addAll(coTrainingSet);
				testSet.addAll(coTestSet);
			}
		} catch (FileNotFoundException fnfe) {
			System.out.println("Stock symbol CSV file does not exist: "
					+ stockSymbolsCSV);
			System.exit(STOCK_SYMBOL_CSV_NOT_FOUND);
		} catch (IOException ioe) {
			System.out.println("Stock symbol CSV file does not exist: "
					+ stockSymbolsCSV);
			System.exit(IO_EXCEPTION);
		}
		
		modelGenerator.ngramModel.reportModel(trainingSet, testSet, stockTrends);
	}

	private List<Company> getFortune50(File csvFile)
			throws FileNotFoundException, IOException {
		List<Company> fortune50 = new ArrayList<Company>();
		FileInputStream fis = new FileInputStream(csvFile);
		InputStreamReader reader = new InputStreamReader(fis);
		BufferedReader buf = new BufferedReader(reader);
		String csvline = null;
		while ((csvline = buf.readLine()) != null) {
			if (csvline.length() == 0) {
				continue;
			}
			String[] fields = csvline.split(",");
			if (fields.length != 3) {
				throw new RuntimeException(
						"Badly formatted csv file name (3 values expected): "
								+ csvline);
			}
			int id = Integer.valueOf(fields[0]);
			fortune50.add(new Company(id, fields[1], fields[2]));
		}
		return fortune50;
	}
}
