package smart_gs.transcription_tool.action;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import smart_gs.GSConstants;
import smart_gs.logical.Preference;
import smart_gs.logical.Spread;
import smart_gs.swingui.WorkspaceWindow;
import smart_gs.transcription_tool.tesseract.Hocr2LineSegXmlConverter;
import smart_gs.transcription_tool.tesseract.HocrDocument;
import smart_gs.transcription_tool.tesseract.HocrLine;
import smart_gs.transcription_tool.tesseract.HocrParseException;
import smart_gs.transcription_tool.tesseract.HocrParser;
import smart_gs.transcription_tool.tesseract.TesseractRunner;
import smart_gs.transcription_tool.tesseract.TesseractRuntimeException;

public class CallTesseractAction implements ActionListener {

	private List<Spread> targetSpreads;
	private String lang;
	private boolean isIDATMode = true; // 読み取りテキストでIDATを更新する
	private boolean isLineNumMode = true; // 読み取りテキストに行数をつける
	private boolean isLineSegmentMode = false; // bboxデータでLine Segmentを更新する
	private boolean isWordDetectionEnabled = true;

	public CallTesseractAction(List<Spread> targets, String lang,
			boolean isIDATMode, boolean isLineNumMode, boolean isLineSegmentMode) {
		this.targetSpreads = targets;
		this.lang = lang;
		this.isLineSegmentMode = isLineSegmentMode;
		this.isIDATMode = isIDATMode;
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		try {
			for (Spread spread : this.targetSpreads) {
				this.processSpread(spread);
			}
		} catch (HocrParseException e) {
			// TODO write error handling
			e.printStackTrace();
		} catch (TesseractRuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	private void processSpread(Spread spread) throws TesseractRuntimeException,
			HocrParseException {
		WorkspaceWindow.getInstance().setSpread(spread);
		String text = this.getFormattedText(spread);
		spread.getOcrIDAT().setSource("</html></xml>"+text+"</html></xml>");
		WorkspaceWindow.getInstance().updateSpread(spread);
		HocrDocument doc = this.spreadToHocrDocument(spread);
		if (this.isLineSegmentMode) {
			String xmlFilePath = Preference.getInstance()
					.getDscFolderPathString()
					+ spread.getFolderPath()
					+ spread.getFileNameWithoutExtension() + ".xml";
			Hocr2LineSegXmlConverter.convert(doc, xmlFilePath, this.isWordDetectionEnabled);
		}
	}

	private String getFormattedText(Spread spread)
			throws TesseractRuntimeException, HocrParseException {
		HocrDocument doc = this.spreadToHocrDocument(spread);
		List<String> formattedLineTexts = new ArrayList<String>();
		for (HocrLine line : doc.getLines()) {
			formattedLineTexts.add(this.formatHocrLine(line));
		}
		//return StringUtils.join(formattedLineTexts, "<br/>");
		return doc.toHtml();
	}

	private String formatHocrLine(HocrLine line) {
		int lineNum = line.getLineNum();
		String text = line.getText();
		if (this.isLineNumMode) {
			return String.format("$%d$ %s", lineNum, text);
		} else {
			return String.format("%s<br/>", lineNum, text);
		}
	}

	private HocrDocument spreadToHocrDocument(Spread spread)
			throws TesseractRuntimeException, HocrParseException {
		TesseractRunner r = new TesseractRunner();
		String in = spread.getFile().getAbsolutePath();
		String tempDir = GSConstants.TEMP_PATH;
		String out = tempDir + System.getProperty("file.separator")
				+ "hocr-temp";
		r.exec(in, out, this.lang);
		HocrParser parser = new HocrParser();
		HocrDocument doc = parser.parse(new File(out + ".html"));
		doc.setFileName(spread.getFileName());
		return doc;

	}

	public List<Spread> getTargetSpreads() {
		return targetSpreads;
	}

	public void setTargetSpreads(List<Spread> targetSpreads) {
		this.targetSpreads = targetSpreads;
	}

	public boolean isTextGenerationMode() {
		return isIDATMode;
	}

	public void setTextGenerationMode(boolean isTextGenerationMode) {
		this.isIDATMode = isTextGenerationMode;
	}

	public boolean isDscGenerationMode() {
		return isLineSegmentMode;
	}

	public void setDscGenerationMode(boolean isDscGenerationMode) {
		this.isLineSegmentMode = isDscGenerationMode;
	}

	public String getLang() {
		return lang;
	}

	public void setLang(String lang) {
		this.lang = lang;
	}

	public boolean isWordDetectionEnabled() {
		return isWordDetectionEnabled;
	}

	public void setWordDetectionEnabled(boolean isWordDetectionEnabled) {
		this.isWordDetectionEnabled = isWordDetectionEnabled;
	}

}
