package smart_gs.image_search.transcription_tool.swingui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.SwingConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.StyleContext;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;

import org.apache.commons.lang.StringEscapeUtils;

import com.hexidec.ekit.component.ExtendedHTMLEditorKit;

import smart_gs.dictionary.viewer.LabelMouseListener;
import smart_gs.drawing_tool.SpreadCanvas;
import smart_gs.image_search.logical.SearchResult;
import smart_gs.image_search.normal.swingui.ResultPopupWindow;
import smart_gs.logical.LineSegment;
import smart_gs.logical.Spread;
import smart_gs.swingui.WorkspaceWindow;
import smart_gs.util.ImageCropper;
import smart_gs.util.SimpleTextLocationEstimator;
import smart_gs.util.TextLocationEstimator;
import sml_editor.logical.LineDirection;
import sml_editor.swingui.GSHTMLEditorTextPane;

@SuppressWarnings("serial")
public class ResultPanel extends JPanel {
	
	private SearchResultListPanel parent;
	private String originalText;	
	private String transcriptionText;
	private int transcriptionIndex;
	private SearchResult result;	
	public SearchResult getResult() {
		return result;
	}

	public void setResult(SearchResult result) {
		this.result = result;
	}

	private JTextField transcriptionField;
	private JCheckBox selectionCheckBox;
	private Image queryImage;
	private LineDirection lineDirection;
	private GSHTMLEditorTextPane tempTextPane;
	
	public ResultPanel(SearchResultListPanel parent, SearchResult result, String transcriptionText, 
			Image queryImage, LineDirection lineDirection) {
		super();
		this.parent = parent;
		this.result = result;		
		this.originalText = this.getTargetLineText();
		this.queryImage = queryImage;
		this.lineDirection = lineDirection;
		this.transcriptionText = transcriptionText;
		TextLocationEstimator locater = new SimpleTextLocationEstimator();
		Rectangle rect = result.getRectangle();
		SpreadCanvas canvas = new SpreadCanvas(result.getSpread());
		List<LineSegment> lines = canvas.getSpread().getLines();
		try {					
			int index = result.getLineIndex();
				LineSegment line = lines.get(index);
			this.transcriptionIndex = 
				locater.guessCharIndex(line, rect.x, rect.y) + 4;		
		} catch (IndexOutOfBoundsException e) {
			System.out.println("Line info not found on canvas.");
		}
		this.setLayout(new BorderLayout());		
	//	this.setBorder(new TitledBorder(documentURI));
		this.setSize(400,50);
		this.add(this.createImageLabel(result),BorderLayout.WEST);		
		this.transcriptionField = this.createTranscriptionField(result);
		this.add(this.transcriptionField,BorderLayout.CENTER);
		this.updateTranscriptionField();
		this.add(this.createManipulationPanel(),BorderLayout.EAST);		
	}
	
	private JPanel createManipulationPanel() {
		JPanel panel = new JPanel();
		panel.setLayout(new GridLayout(2,2));
		JButton transcribeButton = new JButton();
		transcribeButton.setText("Replace");
		transcribeButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				replace();
			}
		});
		panel.add(transcribeButton);
		JButton removeButton = new JButton();
		removeButton.setText("Remove from list");
		removeButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				remove();
			}
		});
		panel.add(removeButton);
		JButton backwardButton = new JButton();
		backwardButton.setText("<<");
		backwardButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (transcriptionIndex > 0) {
					transcriptionIndex--;
					updateTranscriptionField();	
				}
			}});
		panel.add(backwardButton);		
		JButton forwardButton = new JButton();
		forwardButton.setText(">>");
		forwardButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				transcriptionIndex++;
				updateTranscriptionField();
			}});
		panel.add(forwardButton);
		return panel;
	}
	
	private String getTargetLineText() {
		String source = this.result.getSpread().getFirstIDAT().getSource();
		// Convert HTML source to plain text using GSHTMLEditorTextPane
		tempTextPane = new GSHTMLEditorTextPane(null, null);		
		ExtendedHTMLEditorKit htmlKit = new ExtendedHTMLEditorKit();
		tempTextPane.setEditorKit(htmlKit);
		source = source.replaceAll(" ", "&nbsp;");
		tempTextPane.setText(source);
		int linenum = this.result.getLineIndex();
		Document baseDocument = tempTextPane.getDocument();		
		String targetLineText = "";
		try {
			this.originalText = baseDocument.getText(0, baseDocument.getLength());
			String regex = "(\\$"+ linenum +"\\$.*?)\\$";
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(originalText);
			if (m.find()){		
				targetLineText = m.group(1);
			}
		} catch (BadLocationException e) {
			e.printStackTrace();
		}		
		return targetLineText;
	}
	
	private JTextField createTranscriptionField(SearchResult result) {
		JTextField field = new JTextField();
		field.setSize(200,100);
		field.setHorizontalAlignment(SwingConstants.LEFT);
		field.setFont(new Font(StyleContext.DEFAULT_STYLE,Font.PLAIN,20));
		field.setBackground(Color.white);
		field.setOpaque(true);
		field.setEditable(false);
		field.setEnabled(false);
		field.setDisabledTextColor(Color.BLACK);
		return field;
	}
	
	private void remove() {
		this.parent.removeResult(this.result);
		this.parent.showResults();
		this.parent.revalidate();
		this.parent.repaint();
	}
	
	/**
	 * 
	 */
	private void replace(){
		try {
			int linenum = this.result.getLineIndex();
			String plainText = tempTextPane.getDocument().getText(0, tempTextPane.getDocument().getLength());
			Spread spread = this.result.getSpread();
			int lineStartIndex = plainText.indexOf("$"+linenum+"$");			
			tempTextPane.setSelectionStart(transcriptionIndex+lineStartIndex);
			tempTextPane.setSelectionEnd(transcriptionIndex+lineStartIndex+transcriptionText.length());
			tempTextPane.replaceSelection(transcriptionText);
			String replaced = StringEscapeUtils.unescapeHtml(tempTextPane.getText());
			replaced = replaced.substring(replaced.indexOf("<body>")+6, replaced.indexOf("</body>")); 
			spread.getFirstIDAT().setSource("<xml><html>"+replaced+"</html></xml>");
			WorkspaceWindow.getInstance().updateSpread(spread);
			// remove from list
			remove();
		} catch (BadLocationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();	
		}
	}
	
	/**
	 * 置換後の行テキストを生成する
	 * @return
	 */
	private String getSuggestionText(String text){
		String pre;
		String post;
		if(text == null) {
			return originalText;
		}
		if(originalText.length() > text.length() + transcriptionIndex) {
			pre = originalText.substring(0, transcriptionIndex);
			post = originalText.substring(transcriptionIndex+text.length());
			return pre + text + post;
		} else if (originalText.length() < transcriptionIndex){
			int diff = originalText.length() - transcriptionIndex;
			String space = "";
			for (int i=0; i< diff; i++) {space+=" "; }
			pre = originalText + space;
			post = "";
		} else {
			pre = originalText.substring(0, transcriptionIndex);
			post = "";
		}
		return pre + text + post;
	}
	
	public void updateTranscriptionField(){
		this.transcriptionField.setText(this.getSuggestionText(transcriptionText));
		Highlighter hilite = this.transcriptionField.getHighlighter();
		DefaultHighlightPainter hilightPainter = new DefaultHighlightPainter(Color.yellow);
		try {
			hilite.addHighlight(transcriptionIndex, transcriptionIndex + transcriptionText.length(), hilightPainter);
		} catch (BadLocationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int length = this.transcriptionField.getText().length();
		if(this.transcriptionIndex > length) {
			this.transcriptionField.setCaretPosition(length);
		} else {
			this.transcriptionField.setCaretPosition(this.transcriptionIndex+transcriptionText.length());
		}
	}
	

	private JLabel createImageLabel(SearchResult result) {
		Spread spread = result.getSpread();
		Rectangle2D rect = result.getRectangle();
		int width = queryImage.getWidth(null);
		int height = queryImage.getHeight(null);
		
//		//parameters to adjust image size by ImageCropper.crop.
//		if(this.lineDirection == LineDirection.HORIZONTAL){
//			width = width + this.widthCorrectionHmode;
//			height = height + this.heightCorrectionHmode;
//		}else{
//			width = width + this.widthCorrectionVmode;
//			height = height + this.heightCorrectionVmode;
//		}
//		width *= magnification;
//		height *= magnification;
		
		if (this.lineDirection == LineDirection.HORIZONTAL&& height>50) {
			double ratio2 = 50.0 /  height;
			width *= ratio2;
			height *= ratio2;
		} else if (! (this.lineDirection == LineDirection.HORIZONTAL) && width>50) {
			double ratio2 = 50.0 /  width;
			width *= ratio2;
			height *= ratio2;
		}
		
		Image image = new ImageCropper(spread,rect).crop(width,height);
		JLabel label = new JLabel(new ImageIcon(image));
		JWindow window = new ResultPopupWindow(result);
		label.addMouseListener(new LabelMouseListener(label,window,spread,rect));
		return label;
	}
	
	public boolean isSelected() {
		return this.selectionCheckBox.isSelected();
	}
	
	public void setSelected(boolean bool) {
		this.selectionCheckBox.setSelected(bool);		
	}

	public String getTranscriptionText() {
		return transcriptionText;
	}

	public void setTranscriptionText(String transcriptionText) {
		this.transcriptionText = transcriptionText;
	}

	
}
