package com.atlassian.uwc.exporters;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.atlassian.uwc.prep.MoinMoinPreparation.PageDirFileFilter;
import com.atlassian.uwc.ui.FileUtils;

/**
 * Exporter code based on MoinMoinPreparation class. 
 * This is partially a refactor, but also contains some new properties and improvements.
 */
public class MoinmoinExporter implements Exporter {

	private boolean running = false;
	Logger log = Logger.getLogger(this.getClass());
	
	private Map properties;
	private static final String CURRENT = "current";
    private static final String REVISIONS = "revisions";
    private static final String BADCONTENT = "BadContent";
    private static final String CATEGORY = "CategoryRoot";
    private static final String EXTENSION = ".txt";
    public static final String REVLOG = "edit-log";

	
    private class RevInfo{
    	public String userid;
    	public Date timestamp;
    	public String revComment;
    	public Integer revision;
    	public String origAuthor;
    }
    
	public void cancel() {
		log.info("Cancelling Moinmoin Export");
		this.running = false;
	}

	public void export(Map propertiesMap) throws ClassNotFoundException,
			SQLException {
		this.running = true;
		log.info("Beginning Moinmoin Export");
		this.properties = propertiesMap;

		if (validDirectories()) {
			exportPages();
		}
		
		if (this.running)
			log.info("Moinmoin Export Complete");
		this.running = false;
	}

	/**
	 * @return true if the src and out directories are valid directories
	 */
	protected boolean validDirectories() {
		if (this.running == false) return false;
		
		String src = getSrc();
		String out = getOut();
		if (src == null || out == null) {
			log.error("src and out properties must be set in conf/exporter.moinmoin.properties");
			return false;
		}
        File pagesDir = new File(src);
        File destinationDir = new File(out);

        if (pagesDir.isFile() || !pagesDir.exists()) {
        	log.error("src directory is not a valid directory: " + src);
        	return false;
        }


        if (destinationDir.isFile()) {
        	log.error("out property is not a directory: " + out);
        	return false;
        }

        if (!destinationDir.exists()) {
        	if (!destinationDir.mkdirs()) {
        		log.error("Impossible to create out directory: \"" + out + "\".");
            	return false;
        	}
        }
        log.debug("src and out directories are valid");
		return true;
	}

	private String getSrc() {
		if (this.properties == null) return "";
		return (String) this.properties.get("src");
	}

	private String getOut() {
		if (this.properties == null) return "";
		return (String) this.properties.get("out");
	}

	/**
	 * export moinmoin pages to out directory
	 */
	private void exportPages() {
		if (this.running == false) return;
		
		log.debug("src directory: " + getSrc());
		log.debug("out directory: " + getOut());
		
		File pagesDir = new File(getSrc());
		String[] pages = pagesDir.list(new PageDirFileFilter());
        String current = null;

        Map<String, String> usernames = getUserNameInfo(getSrc() + File.separator + ".." );
        Map<String, String> orignames = getOrigNameInfo(getSrc() + File.separator + ".." );

        for (int i = 0; i < pages.length; i++) {
            if (!pages[i].startsWith(BADCONTENT) && !pages[i].startsWith(CATEGORY) ) { //ignore BADCONTENT page
					log.debug("page: " + pages[i]);
            	if (exportHistory()) {
            		final String pagedir = getSrc() + File.separator + pages[i];
            		final String revisiondir = pagedir + File.separator + REVISIONS;
            		log.debug("revision dir: " + revisiondir );
            		
            		String[] revisions = new File(revisiondir).list();
					if (revisions == null) {
						log.error("Revisions directory was null. Skipping.");
						continue;
					}
					
					Map<Integer, RevInfo> revmap = readRevisionsInfo(pagedir, usernames, orignames);
					
            		for (String revision : revisions) {
            			if (!revision.matches("\\d+")) continue; //ignore non-numbers
						int num = Integer.parseInt(revision);
						try {
	            			File srcfile = new File(getSrc() + File.separator + pages[i] + 
								            							File.separator + REVISIONS + File.separator + revision);
	            			File outfile = new File(getOut() + File.separator + pages[i] + "-" + num + EXTENSION);
							copyFile(srcfile,outfile);
							//addTimestampData(outfile, new Date(srcfile.lastModified()));
							addRevData(outfile, revmap.get(num));
							addTitleData(outfile, pages[i]);
	            		} catch (FileNotFoundException e) {
	            			log.info("Page \"" + pages[i] + "\" has been deleted and will be ignored.");
	            		} catch (Exception e) {
	            			e.printStackTrace();
	            		}
					}
            		
            	}
            	else { //only export current
	            	current = getCurrentRevision(getSrc() + File.separator + pages[i]);
	            	log.debug(pages[i] + "\ncurrent revision: " + current);
	            	if (current != null) {
	            		try {
	            			File srcfile = new File(getSrc() + File.separator + pages[i] + 
								            							File.separator + REVISIONS + File.separator + current);
							File outfile = new File(getOut() + File.separator + pages[i] + EXTENSION);
							copyFile(srcfile, outfile);
							addTitleData(outfile, pages[i]);
	            		} catch (FileNotFoundException e) {
	            			log.info("Page \"" + pages[i] + "\" has been deleted and will be ignored.");
	            		} catch (Exception e) {
	            			e.printStackTrace();
	            		}
	            	}
            	}
            }
        }
		
	}
	

	final Charset charset = Charset.forName("windows-1252");
	

	private Map<String, String> getUserNameInfo(String srcDir) {
		Map<String, String> res = new HashMap<String, String>();
		String usersrc = srcDir + File.separator + "user";
		log.debug("read UserInfo: " + usersrc);
		
		Pattern namefinder = Pattern.compile("^aliasname=(\\S+)", Pattern.MULTILINE);
		
		try{
			File userdir = new File(usersrc);
			
			for( File f : userdir.listFiles() ){
				
				log.debug("reading userfile: " + f.getName());
				
				// leave directories out
				if( f.isDirectory() ) continue;
				
				String key = f.getName();
				String cont = FileUtils.readTextFile(f, charset);
				Matcher m = namefinder.matcher(cont);
				if(m.find()){
					String name = m.group(1);
					log.debug(String.format(" Key: %s \t Name %s", key, name));
					res.put(key, name);
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return res;
	}

	private Map<String, String> getOrigNameInfo(String srcDir) {
		Map<String, String> res = new HashMap<String, String>();
		String usersrc = srcDir + File.separator + "user";
		log.debug("read OrigNameInfo: " + usersrc);

		Pattern origNameFinder = Pattern.compile("^name=(\\S+)", Pattern.MULTILINE);

		try{
			File userdir = new File(usersrc);

			for( File f : userdir.listFiles() ){

				log.debug("reading userfile: " + f.getName());

				// leave directories out
				if( f.isDirectory() ) continue;

				String key = f.getName();
				String cont = FileUtils.readTextFile(f, charset);
				Matcher m = origNameFinder.matcher(cont);
				if(m.find()){
					String origName = m.group(1);
					log.debug(String.format(" Key: %s \t OrigName %s", key, origName));
					res.put(key, origName);
				}

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

		return res;
	}

	private void addRevData(File outfile, RevInfo revInfo) {
		final String tsData = "{timestamp:" + fm.format(revInfo.timestamp) + "}\n";
		final String userid = "{userid:" + revInfo.userid + "}\n";
		final String revComment = "{revcomment:" + revInfo.revComment + "}\n";
		// If origAuthor is known, inject it as extra metadata into the exported page so it can be used during conversion
		final String origAuthor = revInfo.origAuthor == null ? "" : "{origauthor:" + revInfo.origAuthor + "}\n";
		
		String filecontents;
		try {
			filecontents = FileUtils.readTextFile(outfile);
		} catch (IOException e) {
			log.error("Could not read output file: " + outfile.getAbsolutePath());
			e.printStackTrace();
			return;
		}
		String newcontents = tsData + userid + revComment + origAuthor + filecontents;
		FileUtils.writeFile(newcontents, outfile.getAbsolutePath());
		
	}

	private Map<Integer, RevInfo> readRevisionsInfo(String pagedir, Map<String, String> usermap, Map<String, String> origNameMap) {
		final File revlogf = new File( pagedir + File.separator + REVLOG);
		final Map<Integer, RevInfo> res = new HashMap<Integer, RevInfo>();
		log.debug("Read reflog file: " + revlogf.getAbsolutePath() );
		
		try {
			final String filecontens = FileUtils.readTextFile(revlogf, charset);
			for( String line : filecontens.split("\\n") ){
				log.debug("read line of revisions file: " + line);
				String[] s = line.split("\\t",9);
				
				RevInfo r = new RevInfo();
				
				r.revision = Integer.parseInt(s[1]);
				res.put(r.revision, r);
				
				if(usermap.containsKey(s[6])){
					r.userid = usermap.get(s[6]);
				} else {
					// make empty, so we get SYSTEM as userid, since there is no useful name anyway
					r.userid = "";
				}
				if(r.userid.trim().equals("")){
					r.userid = "SYSTEM";
				}

				if (origNameMap.containsKey(s[6])) {
					r.origAuthor = origNameMap.get(s[6]);
				}
				
				r.revComment = s[8].trim();
				long time = Long.parseLong(s[0]) / 1000; //convert micro to milliseconds
				r.timestamp = new Date(time);
				

			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}
		
		return res;
	}

	static private SimpleDateFormat fm = new SimpleDateFormat("yyyyMMddHHmmss");
	
	private void addTimestampData(File outfile, Date timestamp) {
		String tsData = "{timestamp:" + fm.format(timestamp) + "}\n";
		String filecontents;
		try {
			filecontents = FileUtils.readTextFile(outfile);
		} catch (IOException e) {
			log.error("Could not read output file: " + outfile.getAbsolutePath());
			e.printStackTrace();
			return;
		}
		String newcontents = tsData + filecontents;
		FileUtils.writeFile(newcontents, outfile.getAbsolutePath());
	}

	
	protected void addTitleData(File outfile, String title) {
		title = title.replaceAll("\\(2f\\)", "/");
		title = title.replaceAll("\\(20\\)", " ");
		title = title.replaceAll("\\(2d\\)", "-");
		String titledata = "{orig-title:" + title + "}\n";
		String filecontents;
		try {
			filecontents = FileUtils.readTextFile(outfile);
		} catch (IOException e) {
			log.error("Could not read output file: " + outfile.getAbsolutePath());
			e.printStackTrace();
			return;
		}
		String newcontents = titledata + filecontents;
		FileUtils.writeFile(newcontents, outfile.getAbsolutePath());
	}

	private boolean exportHistory() {
		if (this.properties == null) return false;
		return Boolean.parseBoolean((String) this.properties.get("history"));
	}
	
	private boolean exportHistoryComments() {
		if (this.properties == null) return false;
		return Boolean.parseBoolean((String) this.properties.get("histcomment"));
	}

	/**
	 * copies file to newFile
	 * @param file
	 * @param newFile
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	protected void copyFile(File file, File newFile) throws FileNotFoundException, IOException {
		if (!this.running) return;
		log.debug("Copying '" + file.getAbsolutePath() + "' to '" + newFile.getAbsolutePath() + "'");
		if (!file.exists()) log.error("File doesn't exist. Cannot copy: " + file.getAbsolutePath());
		// Create channel on the source
		FileChannel srcChannel = new FileInputStream(file.getAbsolutePath()).getChannel();
   
		// Create channel on the destination
		FileChannel dstChannel = new FileOutputStream(newFile.getAbsolutePath()).getChannel();
   
		// Copy file contents from source to destination
		int buffersize = -1;
		try {
			//see if the user specified a buffer size
			String buffersizeStr = (String) this.properties.get("buffer-size");
			if (buffersizeStr != null) {
				try { 
					buffersize = Integer.parseInt(buffersizeStr); 
				}
				catch (NumberFormatException en) {
					log.error("Property buffer-size is not an integer. Using filesize.");
				}
			}
			if (buffersize > 0) { //user set buffersize - see Michael Grove's code in UWC-349
				long size = srcChannel.size();
	            long position = 0;
	            while (position < size) {
	               position += srcChannel.transferTo(position, buffersize, dstChannel);
	            }
			}
			else { //if no user specified buffer size, use filesize
				dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
			}
		} catch (FileNotFoundException e) {
			throw e;
		} catch (IOException e2) {
			throw e2;
		} catch (RuntimeException e3) {
			throw e3;
		} finally {
			// Close the channels
			srcChannel.close(); 
			dstChannel.close();
			if (!newFile.exists()) log.error("Copying file unsuccessful. New file does not exist: " + newFile.getAbsolutePath());
		}
		
	}
	
	  /**
     * getCurrentRevision
     *
     * @param pagePath
     * @return current revision filename
     */
    private String getCurrentRevision(String pagePath) {

        String current = null;
        try {
            BufferedReader br = new BufferedReader(new FileReader(pagePath + File.separator + CURRENT));
            current = br.readLine();
        } catch (FileNotFoundException e) {
        	log.info("Page \"" + pagePath + "\" has been deleted and will be ignored.");
        } catch (IOException e) {
        	e.printStackTrace();
        }
        return current;
    }
	
	//used with unit testing
	protected void setProperties(Map properties) {
		this.properties = properties;
	}

	//used with unit testing
	protected void setRunning(boolean running) {
		this.running = running;
	}

}
