/*
 * Copyright 2020 ETSI
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fr.mines_stetienne.ci.saref.gui;

import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.WindowConstants;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.mines_stetienne.ci.saref.SAREF;
import fr.mines_stetienne.ci.saref.SAREFCredentialsProvider;
import fr.mines_stetienne.ci.saref.SAREFPipeline;
import fr.mines_stetienne.ci.saref.SAREFPipeline.Mode;
import fr.mines_stetienne.ci.saref.managers.RepositoryManager;
import fr.mines_stetienne.ci.saref.tests.TestSuites;

public class MainFrame extends JFrame implements SAREFCredentialsProvider {

	private static final boolean CAN_OPEN = Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN);

	private static final Logger LOG = LoggerFactory.getLogger(MainFrame.class);

	private File directory = null;
	private SAREFPipeline.Mode mode = Mode.DEVELOP;
	private boolean ignoreExamples = false;
	private boolean ignoreTerms = false;
	private boolean ignoreSite = false;

	private final InfoPanel infoPanel = new InfoPanel();
	private final FunctionalitiesPanel functionalitiesPanel = new FunctionalitiesPanel(this);
	private final ConsolePanel consolePanel = new ConsolePanel();

	public MainFrame() {
		super("SAREF Pipeline");
		setBounds(100, 100, 800, 400);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		URL url = MainFrame.class.getClassLoader().getResource("etsi.png");
		ImageIcon img = new ImageIcon(url);
		setIconImage(img.getImage());

		getContentPane().add(infoPanel, BorderLayout.NORTH);
		getContentPane().add(consolePanel, BorderLayout.CENTER);
		getContentPane().add(functionalitiesPanel, BorderLayout.SOUTH);

		functionalitiesPanel.addFileChooserActionListener(new FileChooserActionListener(this));
		functionalitiesPanel.addStartActionListener(new StartActionListener(this));

		pack();
		setResizable(true);
		setVisible(true);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	}

	public void setDirectory(File directory) {
		this.directory = directory;
	}

	public void setMode(SAREFPipeline.Mode mode) {
		this.mode = mode;
	}

	public void setIgnoreSite(boolean ignoreSite) {
		this.ignoreSite = ignoreSite;
	}

	public void setIgnoreExamples(boolean ignoreExamples) {
		this.ignoreExamples = ignoreExamples;
	}

	public void setIgnoreTerms(boolean ignoreTerms) {
		this.ignoreTerms = ignoreTerms;
	}
	
	private class FileChooserActionListener implements ActionListener {
		private final MainFrame mainFrame;

		private FileChooserActionListener(MainFrame mainFrame) {
			this.mainFrame = mainFrame;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser fileChooser = new JFileChooser(directory);
			fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			int option = fileChooser.showOpenDialog(mainFrame);
			if (option == JFileChooser.APPROVE_OPTION) {
				directory = fileChooser.getSelectedFile();
				infoPanel.setDirectory(directory);
				functionalitiesPanel.setEnabled();
			}
		}

	}

	private class StartActionListener implements ActionListener {
		private final MainFrame mainFrame;

		private StartActionListener(MainFrame mainFrame) {
			this.mainFrame = mainFrame;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			SAREFPipeline pipeline = new SAREFPipeline(mainFrame, directory, mode, ignoreExamples, ignoreTerms, ignoreSite);
			consolePanel.clear();
			TestSuites testSuites = pipeline.run();
			if(pipeline.mode == Mode.CLEAN) {
				consolePanel.reportInfo("Project cleaned", "");
				return;
			} else {
				String title = String.format("The SAREF Pipeline completed with %s errors and %s warnings\n", testSuites.getErrors(), testSuites.getFailures());
	
				File report = new File(pipeline.targetDir, "report_output.xml");
				String msg = String.format("<p>Logs and reports: <a href=\"%s\">%s</a></p>", report.toURI(), report.getPath());
				if(!pipeline.ignoreSite) {
					File reportHTML = new File(pipeline.targetDir, "site/report.html");
					msg += String.format("<p>HTML report: <a href=\"%s\">%s</a></p>", reportHTML.toURI(), reportHTML.getPath());				
					if(pipeline.getSourcesManager().getTargetRepositoryManager()!=null) {
						RepositoryManager target = pipeline.getSourcesManager().getTargetRepositoryManager();
						File siteDir = new File(pipeline.targetDir, SAREF.NAME_SITE);
						File ontoDir = new File(siteDir, target.getCurrentVersion().getVersionPath());
						File documentationHTML = new File(ontoDir, String.format("%s.html", target.getRepository().getOntologyFileName()));
						msg += String.format("<p>HTML documentation: <a href=\"%s\">%s</a></p>", documentationHTML.toURI(), documentationHTML.getPath());
					} else {
						File entryPoint = new File(pipeline.targetDir, "site/extensions.html");
						msg += String.format("<p>HTML documentation entrypoint: <a href=\"%s\">%s</a></p>", entryPoint.toURI(), entryPoint.getPath());
					}
				}
				consolePanel.reportInfo(title, msg);
			}
		}

	}

//	public void browseDialog(File file, String messageName) throws IOException {
//		String link = String.format("<a href=\"%s\">%s</a><br/>", file.getCanonicalPath(),
//				file.getCanonicalPath());
//		String message = SAREF.getMessage(messageName, link);
//		JEditorPane messageHTML = new JEditorPane("text/html",
//				String.format("<html><body>%s</body></html>", message));
//		int n = JOptionPane.showConfirmDialog(this, messageHTML, SAREF.getMessage("open_title"),
//				JOptionPane.OK_CANCEL_OPTION);
//		if (n == JOptionPane.YES_OPTION) {
//			Desktop.getDesktop().open(file);
//		}
//	}

	@Override
	public String getUsername(String hostName) {
		return JOptionPane.showInputDialog(this, SAREF.getMessage(MESSAGE.account_name.toString(), hostName), null);
	}

	@Override
	public char[] getPassword(String hostName) {
		String title = SAREF.getMessage(MESSAGE.account_password.toString(), hostName);
		JPanel panel = new JPanel();
		JLabel label = new JLabel(title);
		JPasswordField pass = new JPasswordField(20);
		panel.add(label);
		panel.add(pass);
		int option = JOptionPane.showOptionDialog(this, panel, title, JOptionPane.OK_CANCEL_OPTION,
				JOptionPane.QUESTION_MESSAGE, null, null, null);
		if (option == 0) {
			return pass.getPassword();
		} else {
			LOG.warn(SAREF.getMessage(MESSAGE.account_password_empty.toString(), hostName));
			return "".toCharArray();
		}
	}
}
