/*
 * Copyright (c) 2005-2010 KOM � Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.movement.smarter.dataanalyzer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * Calculates statistics like travel distance, speed, idle time, moving time, phone out time etc. and stores the results within a file.
 * Statistic calculation is based on .if files, which are located in the "smarter/traces-mv/" folders
 * 
 * @author Marcel Verst
 * @version 26.05.2018
 */
public class Statistics {
	// Statistical values for one fieldtest participant
	private double distance;
	private double avSpeed;
	private int idleTime;
	private int movingTime;
	private int phoneOutTime;

	private String filePath;

	ArrayList<IfFileEntry> fileEntries;

	/**
	 * Initialize statistical values
	 */
	public Statistics(String filePath) {
		distance = 0.0;
		avSpeed = 0.0;
		idleTime = 0;
		movingTime = 0;
		phoneOutTime = 0;
		this.filePath = filePath;
		fileEntries = readFile();
	}

	public ArrayList<IfFileEntry> readFile() {
		ArrayList<IfFileEntry> entryList = new ArrayList<IfFileEntry>();
		try {
			//File file = new File("smarter/traces-mv/mobilityTraceFile-File-Modified-10.if");
			File file = new File(filePath);
			if(file.exists()) {
				FileReader fileReader = new FileReader(file);
				BufferedReader bufferedReader = new BufferedReader(fileReader);
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					// line format: 1234 450 123
					// 0 1 2
					String[] split = line.split(" ");
					int lineID = Integer.parseInt(split[0]);
					double x = Double.parseDouble(split[1]);
					double y = Double.parseDouble(split[2]);

					IfFileEntry entry = new IfFileEntry(lineID, x, y);
					entryList.add(entry);
				}
				fileReader.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return entryList;
	}

	/**
	 * Calculates the total distance traveled during the field test
	 * @return the total distance
	 */
	public void calcDistance() {
		double lastX = fileEntries.get(0).getX();
		double lastY = fileEntries.get(0).getY();

		for(int index = 1; index < fileEntries.size(); index++) {
			double newX = fileEntries.get(index).getX();
			double newY = fileEntries.get(index).getY();

			// Pythagoras for distance estimation between two points.
			distance += Math.sqrt(Math.pow(Math.abs(newX - lastX), 2) + Math.pow(Math.abs(newY - lastY), 2));

			lastX = newX;
			lastY = newY;
		}
	}

	/**
	 * Calculates the average speed during the field test
	 * @return the average speed
	 */
	public void calcAvSpeed() {
		// Time difference between end and start of the fieldtest
		int totalTravelTime = fileEntries.get(fileEntries.size()-1).getId() - fileEntries.get(0).getId();

		if(totalTravelTime == 0)
			avSpeed = 0.0;
		else
			avSpeed = distance / totalTravelTime;
	}

	/**
	 * Calculates the time a participant did not move (was idle)
	 * @return the idle time
	 */
	public void calcIdleTime() {
		int lastID = fileEntries.get(0).getId();
		double lastX = fileEntries.get(0).getX();
		double lastY = fileEntries.get(0).getY();

		for(int index = 1; index < fileEntries.size(); index++) {
			int newID = fileEntries.get(index).getId();
			double newX = fileEntries.get(index).getX();
			double newY = fileEntries.get(index).getY();

			// No movement
			if(newX == lastX && newY == lastY)
				idleTime += newID - lastID;

			lastID = newID;
			lastX = newX;
			lastY = newY;
		}
	}

	/**
	 * Calculates the time a participant was moving
	 * @return the moving time
	 */
	public void calcMovingTime() {
		int lastID = fileEntries.get(0).getId();
		double lastX = fileEntries.get(0).getX();
		double lastY = fileEntries.get(0).getY();

		for(int index = 1; index < fileEntries.size(); index++) {
			int newID = fileEntries.get(index).getId();
			double newX = fileEntries.get(index).getX();
			double newY = fileEntries.get(index).getY();
			
			// Movement
			if(!(newX == lastX && newY == lastY))
				movingTime += newID - lastID;

			lastID = newID;
			lastX = newX;
			lastY = newY;
		}
	}

	/**
	 * Calculates the duration how long a phone was outside the pocket. Based on lumen values of the mobile phone sensor
	 * @return the time a phone was out
	 */
	public void calcPhoneOutTime() {
		phoneOutTime = 100;
	}

	public static void clearFile() {
		File file = new File("smarter/statistics/stats.csv");
		PrintWriter writer;
		try {
			writer = new PrintWriter(file);
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Calculates all statistics and stores them in a file
	 */
	public void calcStatistics() {
		try {
			// Create folder if it does not already exist
			File folder = new File("smarter/statistics/");
			if(!folder.exists())
				folder.mkdir();

			//File file = new File("smarter/statistics/stats.txt");
			//PrintWriter printWriter = new PrintWriter(file);
			PrintWriter printWriter = new PrintWriter(new FileOutputStream(
					new File("smarter/statistics/stats.csv"), true));

			if(fileEntries.size() > 0) {
				calcDistance();
				calcAvSpeed();
				calcIdleTime();
				calcMovingTime();
				calcPhoneOutTime();

				// path format: smarter/traces-mv/mobilityTraceFile-File-Modified-10.if
				String[] split = filePath.split("-");
				String appendix = split[4];
				String[] split2 = appendix.split("\\.");
				int id = Integer.parseInt(split2[0]);
				
				// Format of stats.csv: fileID;distance;avSpeed;idleTime;movingTime;phoneOutTime
				printWriter.append(id + ";" + 
						getDistance() + ";" + 
						getAvSpeed() + ";" + 
						getIdleTime() + ";" + 
						getMovingTime() + ";" + 
						getPhoneOutTime() + "\n");
			}

			printWriter.close();			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	// ########## GETTER AND SETTER METHODS ##########
	public double getDistance() {
		return distance;
	}

	public void setDistance(double distance) {
		this.distance = distance;
	}

	public double getAvSpeed() {
		return avSpeed;
	}

	public void setAvSpeed(double avSpeed) {
		this.avSpeed = avSpeed;
	}

	public int getIdleTime() {
		return idleTime;
	}

	public void setIdleTime(int idleTime) {
		this.idleTime = idleTime;
	}

	public int getMovingTime() {
		return movingTime;
	}

	public void setMovingTime(int movingTime) {
		this.movingTime = movingTime;
	}

	public int getPhoneOutTime() {
		return phoneOutTime;
	}

	public void setPhoneOutTime(int phoneOutTime) {
		this.phoneOutTime = phoneOutTime;
	}
	// ###############################################
}
