package com.bayer.edam.excelimport;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.RollingFileAppender;

import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;
import com.univocity.parsers.csv.CsvWriter;
import com.univocity.parsers.csv.CsvWriterSettings;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;

/**
 * Reads the file names from an Toolbox SQL export and copies the actual files
 * from a bcp export done with ToolboxFileExporter to another directory,
 * renaming them to the filenames from the database.
 * 
 * @author gexce
 *
 */
public class CropAssetCopyTool {
	
	private static Logger log = Logger.getLogger(CropAssetCopyTool.class);
	
	private static boolean dryRun = false;
	private static int skipLines = 0;
	
	
	private static String toolboxExportFilePath = "C:\\Temp\\Migration CS - PhotoGallery\\export - 2017-08-25 - assets not included in first migration.csv";
	private static String toolboxExportUpdateFilePath = "C:\\Temp\\Migration CS - PhotoGallery\\export - 2017-08-25 - assets not included in first migration.copytool.csv";
	private static String logfilePath = "C:\\Temp\\Migration CS - PhotoGallery\\export - 2017-08-25 - assets not included in first migration.copytool.log";
	private static String assetPath = "D:\\ToolboxPhotoGallery-numbered";
//	private static String videoPath = "D:\\Toolbox\\Movies\\";
	
	private static File targetDir = new File("D:\\ToolboxPhotoGallery");
//	private static String videoTargetPath = "D:\\UploadVideos";
	
	
	private CsvParserSettings parserSettings = new CsvParserSettings();
	private List<String[]> inputRows;
	private List<String[]> linesForDeletion = new ArrayList<String[]>();
	
	HashSet<Integer> processedAssetIDs = new HashSet<Integer>();
	
	public CropAssetCopyTool() throws IOException {
		
		if (dryRun)
			log.info("This is a dry run. No files are copied.");
		
		if (skipLines > 0)
			log.info("Skipping first " + skipLines + " lines");
		
		
		readToolboxExport();
		
		int lineNo = 0;
		int noFile = 0;
		int noContent = 0;
		int wrongSize = 0;
		int video = 0;
		int zipCorrupt = 0;
		
		for (String[] line : inputRows) {
			lineNo++;
			
			if (lineNo < skipLines) {
				continue;
			}
			
			Integer assetId = Integer.parseInt(line[0]);
			
			if (processedAssetIDs.contains(assetId)) {
				continue;
			}
			
			processedAssetIDs.add(assetId);
			log.debug("Processing AssetID " + assetId + ", line " + lineNo);
			
			String targetName = line[1];
//			long expectedSize = Long.parseLong(line[15]);
			String filePath = assetPath + "\\" + assetId;
			
			File file = new File(filePath);
			long fileLength = file.length();
			
			if (file.isFile()) {
				if (fileLength < 1) {
					noContent++;
					log.warn("Line " + lineNo + ", AssetID " + assetId + " - Skipping file '" + filePath + "', no content. Removing file from list.");
					linesForDeletion.add(line);
				}
//				else if (expectedSize != fileLength) {
//					
//					File videoFile = new File(videoPath + assetId + ".zip");
//					if (videoFile.exists()) {
//						
//						ZipFile zipFile;
//						try {
//							zipFile = new ZipFile(videoFile.getAbsolutePath());
//							
//							@SuppressWarnings("unchecked")
//							List<FileHeader> fileList = (List<FileHeader>) zipFile.getFileHeaders();
//							
//							FileHeader header = null;
//							
//							if (fileList.size() == 1) {
//								header = fileList.get(0);
//							}
//							else {
//								for (FileHeader hdr : fileList) {
//									if (hdr.getFileName().indexOf('/') < 0) {
//										header = hdr;
//										break;
//									}
//								}
//							}
//							
//							log.debug("Extracting " + videoFile.getAbsolutePath());
//							if (!dryRun) {
//								zipFile.extractFile(header, videoTargetPath);
//								File srcFile = new File(videoTargetPath + "\\" + header.getFileName());
//								File destFile = new File(videoTargetPath + "\\" + targetName);
//								log.info("Line " + lineNo + ", AssetID " + assetId + ": Moving " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
//								
//								try {
//									FileUtils.moveFile(srcFile, destFile);
//								}
//								catch (IOException ioe) {
//									log.error("Line " + lineNo + ", AssetID " + assetId + " - IOException: '" + ioe.getMessage() + "'");
//									ioe.printStackTrace();
//								}
//							}
//							
//							video++;
//							
//						} catch (ZipException e) {
//							zipCorrupt++;
//							log.error("Skipping line " + lineNo + ", AssetID " + assetId + " - could not open ZIP file " + videoFile.getAbsolutePath());
//							linesForDeletion.add(line);
//						}
//					}
//					else {
//						wrongSize++;
//						log.debug("Wrong file size for " + assetId + ": expected " + expectedSize + ", found " + fileLength + " (" + targetName + ")");
//					}
//				}
				else {
					File targetFile = new File(targetDir + "\\" + targetName);
					
					if (targetFile.exists()) {
						while (targetFile.exists()) {
							String oldName = FilenameUtils.removeExtension(targetFile.getName());
							String extension = FilenameUtils.getExtension(targetFile.getName());
							String newName = oldName + "--002." + extension;
							if (oldName.length() > 5 && oldName.charAt(oldName.length() - 5) == '-'
									&& oldName.charAt(oldName.length() - 4) == '-'
									&& StringUtils.isNumeric(oldName.substring(oldName.length() - 3))) {
								int num = Integer.parseInt(oldName.substring(oldName.length() - 3));
								num++;
								newName = oldName.substring(0, oldName.length() - 3) + String.format("%03d", num) + "." + extension; 
							}
							targetFile = new File(targetDir + "\\" + newName);
						}
						
						log.info("Line " + lineNo + ", AssetID " + assetId + ": Target file '" + targetName + "' already exists. Copy file as '" + targetFile.getName() + "'");
						line[1] = targetFile.getName();
					}
					
					log.debug("Copy " + file.getAbsolutePath() + " (AssetID " + assetId + ") to " + targetFile.getAbsolutePath());
					
					if (!dryRun) {
						try {
							FileUtils.copyFile(file, targetFile, false);
						}
						catch (IOException ioe) {
							log.error("Line " + lineNo + ", AssetID " + assetId + " - IOException: '" + ioe.getMessage() + "'");
							ioe.printStackTrace();
						}
					}
				}
			}
			else {
				log.error("Line " + lineNo + ", AssetID " + assetId + " - '" + filePath + "' not found");
				noFile++;
			}
		}
		
		log.debug("Removing marked lines... " + inputRows.size());
		inputRows.removeAll(linesForDeletion);
		
		writeImportFile();
		
		log.info("Lines processed: " + lineNo);
		log.info("Assets processed: " + processedAssetIDs.size());
		log.info("Skipped: File not found: " + noFile);
		log.info("Skipped: No content: " + noContent);
		log.info("Wrong size: " + wrongSize);
		
		log.info("Videos: " + video);
		log.info("  Corrupt: " + zipCorrupt);
		
	}
	
	private void readToolboxExport() {
		parserSettings.getFormat().setLineSeparator("\r\n");
		parserSettings.getFormat().setDelimiter(';');
		parserSettings.getFormat().setCharToEscapeQuoteEscaping('"');
		parserSettings.setHeaderExtractionEnabled(false);

		CsvParser parser = new CsvParser(parserSettings);

		inputRows = parser.parseAll(new File(toolboxExportFilePath));
	}

	private void writeImportFile() {
		CsvWriterSettings writerSettings = new CsvWriterSettings();
		writerSettings.setFormat(parserSettings.getFormat());
		
		List<Object[]> csvOutputList = new ArrayList<Object[]>();
		for (String[] line : inputRows) {
			csvOutputList.add(line);
		}

		CsvWriter writer = new CsvWriter(new File(toolboxExportUpdateFilePath), writerSettings);
		writer.writeRowsAndClose(csvOutputList);
	}
	
	public static void main(String[] args) {
		try {
			Layout layout = new PatternLayout("%d{ISO8601} - %p %m%n"); // "%d{ISO8601} - %p %m%n"
			BasicConfigurator.configure(new ConsoleAppender(layout));
			BasicConfigurator.configure(new RollingFileAppender(layout, logfilePath, false));
			log.setLevel(Level.INFO);

			new CropAssetCopyTool();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
