package io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import data.Repository;
import main.Config;

public class Writer {
	/**
	 * Writes in the xml database
	 * 
	 * @author Lisa Nguyen Quang Do
	 */

	// Cell (0,0) contains the row number of the first free row
	// Repositories start at row 5
	// Legend is at row 3

	private final String resultFile;
	private final String worksheetName;

	public Writer(String resultFile, String worksheetName) {
		this.resultFile = resultFile;
		this.worksheetName = worksheetName;
	}

	public void writeSearchInfo(Repository repo) {

		int currentRow = getLastRowInFile();
		if (currentRow < Config.firstRow)
			throw new RuntimeException("Error in writing " + repo);

		writeInfo(currentRow, Config.XML_id, repo.id + "");
		writeInfo(currentRow, Config.XML_name, repo.name);
		writeInfo(currentRow, Config.XML_description, repo.description);
		writeInfo(currentRow, Config.XML_url, repo.html_url);
		writeInfo(currentRow, Config.XML_owner, repo.owner);
		writeInfo(currentRow, Config.XML_ownerType, repo.ownerType);
		writeInfo(currentRow, Config.XML_creationDate, repo.creation_date);
		writeInfo(currentRow, Config.XML_updateDate, repo.latest_update);
		writeInfo(currentRow, Config.XML_size, repo.size);
		writeInfo(currentRow, Config.XML_score, repo.score);
		writeInfo(currentRow, Config.XML_starred, repo.starred);
		writeInfo(currentRow, Config.XML_watched, repo.watched);
		writeInfo(currentRow, Config.XML_licence, repo.license);
		writeInfo(currentRow, Config.XML_wiki, repo.hasWiki + "");
		writeInfo(currentRow, Config.XML_private, repo.isPrivate + "");
		writeInfo(currentRow, Config.XML_downloads, repo.hasDownloads + "");
		writeInfo(currentRow, Config.XML_forks, repo.forks);
		writeInfo(currentRow, Config.XML_releasesUrl, repo.releases_url);
		writeInfo(currentRow, Config.XML_commitsUrl, repo.commits_url);
		writeInfo(currentRow, Config.XML_contributorsUrl, repo.contributors_url);
		writeInfo(currentRow, Config.XML_issuesUrl, repo.issues_url);
		writeInfo(currentRow, Config.XML_contentsUrl, repo.contents_url);
		writeInfo(currentRow, Config.XML_openIssues, repo.open_issues);

		writeInfo(0, 0, currentRow + 1);
	}

	public void writeInfo(int rowId, int cellId, String value) {

		try {
			FileInputStream fileInputStream = new FileInputStream(resultFile);
			Workbook workbook;
			workbook = WorkbookFactory.create(fileInputStream);
			Sheet sheet = workbook.getSheet(worksheetName);

			Row row = sheet.getRow(rowId);
			if (row == null)
				row = sheet.createRow(rowId);
			Cell cell = row.createCell(cellId);
			cell.setCellValue(value);

			fileInputStream.close();

			FileOutputStream outFile = new FileOutputStream(new File(resultFile));
			workbook.write(outFile);
			outFile.close();

		} catch (EncryptedDocumentException | InvalidFormatException | IOException e) {
			e.printStackTrace();
		}
	}

	public void writeInfo(int rowId, int cellId, int value) {
		try {

			FileInputStream fileInputStream = new FileInputStream(resultFile);
			Workbook workbook;
			workbook = WorkbookFactory.create(fileInputStream);
			Sheet sheet = workbook.getSheet(worksheetName);

			Row row = sheet.getRow(rowId);
			if (row == null)
				row = sheet.createRow(rowId);
			Cell cell = row.createCell(cellId);
			cell.setCellValue(value);

			fileInputStream.close();

			FileOutputStream outFile = new FileOutputStream(new File(resultFile));
			workbook.write(outFile);
			outFile.close();

		} catch (EncryptedDocumentException | InvalidFormatException | IOException e) {
			e.printStackTrace();
		}
	}

	private int getLastRowInFile() {
		File f = new File(resultFile);

		if (!f.exists()) {
			Workbook workbook = new HSSFWorkbook();
			createSheet(workbook, f);
			return Config.firstRow;

		} else {
			FileInputStream fileInputStream = null;
			Workbook workbook = null;
			int ret = -1;

			try {
				fileInputStream = new FileInputStream(f);
				workbook = WorkbookFactory.create(fileInputStream);
				Sheet sheet = workbook.getSheet(worksheetName);
				if (sheet == null)
					sheet = createSheet(workbook, f);

				Row row = sheet.getRow(0);
				Cell cell = row.getCell(0);
				ret = (int) cell.getNumericCellValue();

			} catch (IOException | EncryptedDocumentException | InvalidFormatException e) {
				e.printStackTrace();
			} finally {
				if (fileInputStream != null && workbook != null) {
					try {
						workbook.close();
						fileInputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			return ret;
		}
	}

	private Sheet createSheet(Workbook workbook, File f) {
		Sheet sheet = workbook.createSheet(worksheetName);

		Row row = sheet.createRow(0);
		Cell cell = row.createCell(0);
		cell.setCellValue(Config.firstRow);

		row = sheet.createRow(Config.legendRow);

		cell = row.createCell(Config.XML_id);
		cell.setCellValue("Id");

		cell = row.createCell(Config.XML_name);
		cell.setCellValue("Name");

		cell = row.createCell(Config.XML_description);
		cell.setCellValue("Description");

		cell = row.createCell(Config.XML_url);
		cell.setCellValue("HTML url");

		cell = row.createCell(Config.XML_owner);
		cell.setCellValue("Owner");

		cell = row.createCell(Config.XML_ownerType);
		cell.setCellValue("Owner type");

		cell = row.createCell(Config.XML_creationDate);
		cell.setCellValue("Creation date");

		cell = row.createCell(Config.XML_updateDate);
		cell.setCellValue("Update date");

		cell = row.createCell(Config.XML_size);
		cell.setCellValue("Size (kB)");

		cell = row.createCell(Config.XML_score);
		cell.setCellValue("Score");

		cell = row.createCell(Config.XML_starred);
		cell.setCellValue("Starred");

		cell = row.createCell(Config.XML_watched);
		cell.setCellValue("Watched");

		cell = row.createCell(Config.XML_licence);
		cell.setCellValue("Licence");

		cell = row.createCell(Config.XML_wiki);
		cell.setCellValue("has Wiki");

		cell = row.createCell(Config.XML_downloads);
		cell.setCellValue("has Downloads");

		cell = row.createCell(Config.XML_private);
		cell.setCellValue("is Private");

		cell = row.createCell(Config.XML_forks);
		cell.setCellValue("Forks");

		cell = row.createCell(Config.XML_releasesUrl);
		cell.setCellValue("Relesases");

		cell = row.createCell(Config.XML_commitsUrl);
		cell.setCellValue("Commits");

		cell = row.createCell(Config.XML_contributorsUrl);
		cell.setCellValue("Contributors");

		cell = row.createCell(Config.XML_issuesUrl);
		cell.setCellValue("Issues");

		cell = row.createCell(Config.XML_contentsUrl);
		cell.setCellValue("Contents");

		cell = row.createCell(Config.XML_openIssues);
		cell.setCellValue("Open issues");

		FileOutputStream fileOutputStream = null;
		try {
			fileOutputStream = new FileOutputStream(f);
			workbook.write(fileOutputStream);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileOutputStream != null && workbook != null) {
				try {
					workbook.close();
					fileOutputStream.flush();
					fileOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return sheet;
	}
}
