package rdms;

import rdms.Meter;
import rdms.MeterRead;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;

import com.toshiba.mwcloud.gs.Collection;
import com.toshiba.mwcloud.gs.GridStore;
import com.toshiba.mwcloud.gs.Query;
import com.toshiba.mwcloud.gs.RowSet;

// In the commented out functions, I plan to replace Timestamp with a date
// I also plan to replace my repeated conversion from date to timestamp in MySQLIngest with an actual function
public class Ingest {
	protected Meter meter;
	protected MeterRead meterRead;
	
	Calendar last_reading; // this will be used to measure what the last timestamp was in comparison to this one
	
	int option;
	Date endTime;
	boolean isEnded = false;
	int countNum = 0;
	
	int stopNumber = 0;
	
	int mins = 1;
	boolean isSet = true;
	// Constructors
	public Ingest() {
		meter = new Meter();
		meterRead = new MeterRead();
		
		Date tempDate = new Date();
		
		meterRead.all_time_usage = 0;
		meterRead.usage_since_read = 0;
		//meterRead.usage_this_hour = 0;
		meterRead.usage_this_day = 0;
		meterRead.usage_this_week = 0;
		meterRead.usage_this_month = 0;
		meterRead.usage_this_year = 0;
		meterRead.timestamp = tempDate;
		meterRead.error_code_1 = 0;
		meterRead.error_code_2 = 0;
		
		meter.id = 0;
		meter.last_reading = tempDate;
		meter.latitude = (float) 0.0;
		meter.longitude = (float) 0.0;
		
		option = 0;
	}
	public void setTimes(int minutes) {
		mins = minutes;
	}
	public Ingest(Meter m, MeterRead mr) {
		meter = m;
		meterRead = mr;
		
		option = 0;
	}
	
	public void setOption(int op) {
		option = op;
	}
	public int getOption() {
		return option;
	}
	
	public void connectToServer() {}
	public void connectToServer(GridStore s) {}
	public void connectToServer(Connection s) {}
	public void closeServer() {}
	public void generateData() {}
	// for updating usage. Updates the private MeterReads variable automatically.
	//public void setMeterReadFromDB(T key) {}
	// Get data from database without changing any variables within the function
	/*public MeterRead getMeterReadFromDB(Timestamp key) {
		MeterRead meterRead1 = new MeterRead();
		
		return meterRead1;
	}*/
	public Meter getMeterFromDB(long id) {
		Meter meter1 = new Meter();
		
		return meter1;
	}
	// Boolean checks to see if data exists
	public boolean checkMeterExistsDB(long key) { 
		return false;
	}
	/*public boolean checkMeterReadExistsDB(Timestamp key) {
		return false;
	}*/
	// functions verified to be added, below
	public void updateUsage() {
		GregorianCalendar cal_last = new GregorianCalendar();
		//
		Meter tempMeter = new Meter();
		MeterRead tempMeterRead = new MeterRead();
		//
		if(meter != null) {
			if(checkMeterExistsDB(meter.id)) {
				tempMeter = getMeterFromDB(meter.id);
				cal_last.setTime(tempMeter.last_reading);
			}
		}
		Random random = new Random();
		random.setSeed(meter.id + System.nanoTime() + (new Date()).getTime());
		double usage = random.nextDouble();
		if(usage < 0 ) 
			usage = 0-usage;
		Calendar cal = Calendar.getInstance();
		Calendar cal1 = Calendar.getInstance();
		Date lastDate = new Date();
		if(meterRead == null) {
			meterRead = new MeterRead();
			meterRead.timestamp = cal_last.getTime();
		} else if(meterRead.timestamp == null) {
			meterRead.timestamp = cal_last.getTime();
		}
		if(meterRead != null && meterRead.timestamp != null) {
			if(tempMeterRead.timestamp == null)
				tempMeterRead.timestamp = new Date();
			lastDate.setTime(tempMeterRead.timestamp.getTime() + 0);
			
			Date currentDay = new Date();
			cal1.setTime(currentDay);
			if(last_reading == null) {
				
			}
			else {
				cal_last.setTime(last_reading.getTime());
				if(option == 1) {
					cal1.setTime(last_reading.getTime());
					cal1.add(Calendar.MINUTE, mins);
				}
			}
			
			cal.setTime(cal_last.getTime());
			//int daysSinceRead = cal1.get(Calendar.DAY_OF_YEAR) - cal.get(Calendar.DAY_OF_YEAR);
			if(cal.get(Calendar.HOUR_OF_DAY) != cal1.get(Calendar.HOUR_OF_DAY)) {
				meterRead.usage_this_hour = usage;
			} else {
				meterRead.usage_this_hour += usage;
			}
			if(cal.get(Calendar.DAY_OF_YEAR) != cal1.get(Calendar.DAY_OF_YEAR)) {
				//daily = 0;
				//lastDate = currentDay;
				meterRead.usage_this_day = usage;
			} else {
				meterRead.usage_this_day += usage;
			}
			if((cal1.get(Calendar.WEEK_OF_YEAR) != cal.get(Calendar.WEEK_OF_YEAR))) {
				meterRead.usage_this_week = usage;
			} else {
				meterRead.usage_this_week += usage;
			}
			if((cal.get(Calendar.MONTH) - cal1.get(Calendar.MONTH)) > 0) {
				meterRead.usage_this_month = usage;
			} else {
				meterRead.usage_this_month += usage;
			}
			if((cal.get(Calendar.YEAR) - cal1.get(Calendar.YEAR)) > 0) {
				meterRead.usage_this_year = usage;
			} else {
				meterRead.usage_this_year += usage;
			}
			//
			if(option == 0) {
				meterRead.timestamp = new Date();
			} else if(option == 1) {
				meterRead.timestamp = cal1.getTime();
			}
			
			meterRead.all_time_usage += usage;
			
			meterRead.usage_since_read = usage;
			
			meter.last_reading = meterRead.timestamp;
			
			last_reading = Calendar.getInstance();
			last_reading.setTime(meter.last_reading);
		}
	}
	public void writeToDatabase() {}
	
	public boolean isEnded() {
		return isEnded;
	}
	public Date getEndTime() {
		return endTime;
	}
	public void setStopNum(int num) {
		stopNumber = num;
	}
	public void run() {
		countNum = 0;
		int count = 0;
		boolean stopForTest = true;
		int waitSeconds = 60;
		int threadSeconds = waitSeconds * 1000;
		
		int stopNum = stopNumber;
		
		try {
			if(!isSet)
				connectToServer();
			while(true) {
				count++;
				//System.out.println("Running time " + count);
				//meterRead.usage_since_read = 0;
				updateUsage();
				writeToDatabase();
				if(stopForTest && count == stopNum) {
					endTime = new Date();
					countNum = count;
					isEnded = true;
					break;
				}
				if(option == 0) {
					Thread.sleep((threadSeconds));
				}
			}
		} catch (InterruptedException e) {
			System.out.println("Thread was interrupted");
			e.printStackTrace();
		}
		if(!isSet)
			closeServer();
	}
	
	//
	public void setMeter(Meter m) {
		meter = new Meter();
		meter = m;
	}
	public void setMeterRead(MeterRead mr) {
		meterRead = new MeterRead();
		meterRead = mr;
		meterRead.usage_this_month = mr.usage_this_month;
	}
	public Meter getMeter() {
		return meter;
	}
	public MeterRead getMeterRead() {
		return meterRead;
	}
	
	// For testing
	public void runOnce() {
		updateUsage();
		writeToDatabase();
	}
	/*
	public void connectToServer(GridStore s, ServerConnection se) {
		// TODO Auto-generated method stub
		
	}
	public void connectToServer(Connection s, ServerConnection se) {
		
	}
	*/
	public void setUp2(Collection<String, Meter> mcol, RowSet<Meter> mrows, Query<Meter> mquery) {
		// TODO Auto-generated method stub
		
	}
}