package lu.tudor.santec.gecamed.core.gui.utils;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

import lu.tudor.santec.dicom.gui.ErrorDialog;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.LoginScreen;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.jgoodies.forms.builder.ButtonBarBuilder;

public class LogFileViewer {
    
    /**
     * static logger for this class
     */
    private static Logger logger = Logger.getLogger(LogFileViewer.class
	    .getName());
    
    private static final String DATE_PATTERN = "yyyy-MM-dd_HH-mm-ss";
    
    /**
     * shows a dialog with the lient logfile and option to save and print it 
     */
    public static void showLogFile(JFrame owner, String title) {
	final JDialog jd = new JDialog(owner, title);
	showFile(jd, title, readClientLog(), true);
    }

    
    /**
     * shows a dialog with the lient logfile and option to save and print it 
     */
    public static void showLogFile(JFrame owner, String title, String content, boolean set2End) {
	final JDialog jd = new JDialog(owner, title);
	showFile(jd, title, content, set2End);
    }
    
    /**
     * shows a dialog with the lient logfile and option to save and print it 
     */
    public static void showLogFile(JDialog owner, String title, String content, boolean set2End) {
	final JDialog jd = new JDialog(owner, title);
	showFile(jd, title, content, set2End);
    }
    
    /**
     * shows a dialog with the lient logfile and option to save and print it 
     */
    public static void showLogFile(JDialog owner, String title) {
	final JDialog jd = new JDialog(owner, title);
	showFile(jd, title, readClientLog(), true);
    }
    
    private static void showFile(final JDialog jd, final String title, String content, boolean set2End) {
    	
		jd.setLayout(new BorderLayout(4,4));
		final JTextArea jta = new JTextArea();
		try {
			jta.setFont(new Font("monospaced", Font.PLAIN, 12));			
		} catch (Exception e) {
			logger.warn("Error Setting Font");
		}
		
		JButton saveButton = new JButton(Translatrix.getTranslationString("core.save"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.SAVE));
		saveButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser jf = new JFileChooser();
				File f = new File("GECAMED_"+title+"_" + new SimpleDateFormat(DATE_PATTERN).format(new Date()) + ".log");
				jf.setSelectedFile(f);
				if (jf.showSaveDialog(jd) == JFileChooser.APPROVE_OPTION) {
					try {
					    BufferedWriter bw = new BufferedWriter(new FileWriter(jf.getSelectedFile()));
					    bw.write(jta.getText());
					    bw.close();
					} catch (Exception e) {
					    logger.log(Level.WARN,"" ,e);
					}
				}
			}
		});
		
		
		JButton printButton = new JButton(Translatrix.getTranslationString("core.print"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.PRINT));
		printButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			    
			    try {
				File tmp = File.createTempFile("gecamed_log", "log");
				
				BufferedWriter bw = new BufferedWriter(new FileWriter(tmp));
				bw.write(jta.getText());
				bw.close();
				
				SimpleFilePrinter sfp = new SimpleFilePrinter(tmp.getAbsolutePath(), 4);
				if (sfp.setupPageFormat()) {
				    if (sfp.setupJobOptions()) {
					try {
					    sfp.printFile();
					} catch (Exception ee) {
					    logger.log(Level.WARN,"" ,ee);
					    ErrorDialog.showErrorDialog(jd, ee);
						}
				    	}
			    	}
				
			    } catch (Exception e) {
				
			    }
			}
		});
		
		ButtonBarBuilder bb = new ButtonBarBuilder();
		bb.addGlue();
		bb.addGridded(saveButton);
		bb.addRelatedGap();
		bb.addGridded(printButton);
		
		jd.add(bb.getPanel(), BorderLayout.NORTH);
		
		jta.setText(content);
		
	    // Highlight the occurrences of the word "WARNING"
	    highlight(jta, "WARNING");
		
		jd.add(new JScrollPane(jta));
		
		Dimension l_ScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int l_Height = l_ScreenSize.height - 70;
		int l_Width = (int)(l_Height/1.4142);
		
		jd.setLocation(10,10);
		jd.setSize(l_Width,l_Height);
		
		if (! set2End) {
			try {
				jta.setCaretPosition(0);
				jta.scrollRectToVisible(jta.modelToView(0));				
			} catch (Exception e) {
			}
		}
		
		jd.setModal(true);
		jd.setVisible(true);
	}
    
    
	public static String readClientLog()
	{
		final File logFile = getClientLogFile();
		
		try
		{
			BufferedReader br = new BufferedReader(new FileReader(logFile));
			StringBuffer sb = new StringBuffer();
			String line;
			do
			{
				line = br.readLine();
				sb.append(line + "\r\n");
			}
			while (line != null);
			return sb.toString();
		}
		catch (Exception ee)
		{
			ee.printStackTrace();
		}
		return "";
	}
	
	
	public static File getClientLogFile()
	{
		return new File(LoginScreen.LOGFILE.getAbsolutePath());
	}
    
    
    // Creates highlights around all occurrences of pattern in textComp
    public static void highlight(JTextComponent textComp, String pattern) {
        // First remove all old highlights
        removeHighlights(textComp);
        Highlighter.HighlightPainter infoHighlightPainter = new MyHighlightPainter(new Color(255,255,130));
        Highlighter.HighlightPainter warningHighlightPainter = new MyHighlightPainter(new Color(255,118,118));
        try {
            Highlighter hilite = textComp.getHighlighter();
            Document doc = textComp.getDocument();
            String text = doc.getText(0, doc.getLength());
            
            Pattern p = Pattern.compile("^INFO.*$", Pattern.MULTILINE);
            Matcher m = p.matcher(CharBuffer.wrap(text.toCharArray()));
            while (m.find()) {
                hilite.addHighlight(m.start(), m.end(), infoHighlightPainter);
            }
            
            Pattern pw = Pattern.compile("^WARNING.*$", Pattern.MULTILINE);
            Matcher mw = pw.matcher(CharBuffer.wrap(text.toCharArray()));
            while (mw.find()) {
                hilite.addHighlight(mw.start(), mw.end(), warningHighlightPainter);
            }
    
        } catch (BadLocationException e) {
        }
    }
    
    // Removes only our private highlights
    public static void removeHighlights(JTextComponent textComp) {
        Highlighter hilite = textComp.getHighlighter();
        Highlighter.Highlight[] hilites = hilite.getHighlights();
    
        for (int i=0; i<hilites.length; i++) {
            if (hilites[i].getPainter() instanceof MyHighlightPainter) {
                hilite.removeHighlight(hilites[i]);
            }
        }
    }
}
