/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */
package org.greenstone.gatherer.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;
import org.greenstone.gatherer.shell.GShell;
import org.greenstone.gatherer.shell.GShellEvent;
import org.greenstone.gatherer.shell.GShellListener;
import org.greenstone.gatherer.shell.GShellProgressMonitor;


/** A dialog which provides a straight-forward access to the currently installed collections. It also will contain the ability to continue through to the original OpenCollectionDialog if your source collection is located somewhere other than the gsdl collect folder. */
public class OpenCollectionDialog
    extends ModalDialog {

    static final public int OK_OPTION = 0;
    static final public int CANCEL_OPTION = 1;

    static final private Dimension SIZE = new Dimension(640,480);
    static final private String BLANK = "b";
    static final private String DESCRIPTION = "d";

    private CardLayout card_layout;
    private int result;
    private JButton cancel_button;
    private JButton chdir_button;
    private JButton open_button;
    private JList collection_list;
    private JTextArea description_textarea;
    private JPanel description_pane;
    private String filename;
    private String newCollectPath;

    public OpenCollectionDialog() {
	super(Gatherer.g_man, "", true);
	setJMenuBar(new SimpleMenuBar("openingacollection"));
        this.setComponentOrientation(Dictionary.getOrientation());
	setSize(SIZE);
	setTitle(Dictionary.get("OpenCollectionDialog.Title"));
	newCollectPath = Gatherer.getCollectDirectoryPath();

	// Creation
	JPanel content_pane = (JPanel) getContentPane();
        content_pane.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel center_pane = new JPanel();
        center_pane.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel collection_list_pane = new JPanel();
        collection_list_pane.setComponentOrientation(Dictionary.getOrientation());
	JLabel collection_list_label = new JLabel(Dictionary.get("OpenCollectionDialog.Available_Collections"));
        collection_list_label.setComponentOrientation(Dictionary.getOrientation());
	collection_list = new JList(new CollectionListModel());
        collection_list.setComponentOrientation(Dictionary.getOrientation());
        
	description_pane = new JPanel();
        description_pane.setComponentOrientation(Dictionary.getOrientation());
	card_layout = new CardLayout();
        
	JPanel blank_pane = new JPanel();
        blank_pane.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel description_textarea_pane = new JPanel();
        description_textarea_pane.setComponentOrientation(Dictionary.getOrientation());
	JLabel description_textarea_label = new JLabel(Dictionary.get("OpenCollectionDialog.Description"));
        description_textarea_label.setComponentOrientation(Dictionary.getOrientation());
	description_textarea = new JTextArea();
        description_textarea.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel button_pane = new JPanel();
        button_pane.setComponentOrientation(Dictionary.getOrientation());
	open_button = new GLIButton(Dictionary.get("OpenCollectionDialog.Open"), Dictionary.get("OpenCollectionDialog.Open_Tooltip"));
	open_button.setEnabled(false);
	chdir_button = new GLIButton(Dictionary.get("General.CD"), Dictionary.get("General.CD_Tooltip"));
	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
	
	// Connection
	chdir_button.addActionListener(new ChangeDirListener());
	if(Gatherer.isGsdlRemote || Gatherer.isWebswing) { // disable changing directories for client GLI
	    chdir_button.setEnabled(false);
	}
	cancel_button.addActionListener(new CancelListener());
	open_button.addActionListener(new OpenListener());
	CollectionListSelectionListener clsl = new CollectionListSelectionListener();
	collection_list.addListSelectionListener(clsl);
	collection_list.addMouseListener(clsl);
	clsl = null;

	// Layout
        JScrollPane scrol_tmp;
        
	collection_list_pane.setLayout(new BorderLayout());
	collection_list_pane.add(collection_list_label, BorderLayout.NORTH);
        scrol_tmp = new JScrollPane(collection_list);
        scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
	collection_list_pane.add(scrol_tmp, BorderLayout.CENTER);

	description_textarea_pane.setLayout(new BorderLayout());
	description_textarea_pane.add(description_textarea_label, BorderLayout.NORTH);
	scrol_tmp =new JScrollPane(description_textarea);
        scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
        description_textarea_pane.add(scrol_tmp, BorderLayout.CENTER);

	description_pane.setLayout(card_layout);
	description_pane.add(description_textarea_pane, DESCRIPTION);
	description_pane.add(blank_pane, BLANK);

	center_pane.setLayout(new GridLayout(2,1,0,5));
	center_pane.add(collection_list_pane);
	center_pane.add(description_pane);

	button_pane.setLayout(new GridLayout(1,3));
	button_pane.add(open_button);
	button_pane.add(chdir_button);
	button_pane.add(cancel_button);

	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	content_pane.setLayout(new BorderLayout());
	content_pane.add(center_pane, BorderLayout.CENTER);
	content_pane.add(button_pane, BorderLayout.SOUTH);
	// Final dialog setup & positioning.
	getRootPane().setDefaultButton(open_button);
	Dimension screen_size = Configuration.screen_size;
	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
	screen_size = null;
    }

    public void destroy() {
    }

    public int display() {
	setVisible(true);
	return result;
    }

    public String getFileName() {
	return this.filename;
    }

    private class ChangeDirListener implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    JFileChooser chooser = new JFileChooser(newCollectPath);
	    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
	    chooser.setDialogTitle(Dictionary.get("General.ChooseCollectDirectory"));
	    int returnVal = chooser.showOpenDialog(OpenCollectionDialog.this);
	    if(returnVal == JFileChooser.APPROVE_OPTION) {
		String oldCollectPath = newCollectPath;
		newCollectPath = chooser.getSelectedFile().getAbsolutePath() + File.separator;
		
		if(!newCollectPath.equals(oldCollectPath)) {
		    // reload the list of available collections using this new path
		    CollectionListModel listModel = (CollectionListModel)collection_list.getModel();
		    listModel.reload(newCollectPath);
		    collection_list.repaint();
		}
	    } 
	}
    }

    private class CancelListener
	implements ActionListener {

	public void actionPerformed(ActionEvent event) {
	    result = CANCEL_OPTION;
	    OpenCollectionDialog.this.dispose();
	}
    }

    private class CollectionListSelectionListener
	extends MouseAdapter
	implements ListSelectionListener {

	public void mouseClicked(MouseEvent event) {
	    ///ystem.err.println("Mouse clicked");
	    if(event.getClickCount() >= 2) {
		Point location = event.getPoint();
		int index = collection_list.locationToIndex(location);
		collection_list.setSelectedIndex(index);
		location = null;
		open_button.doClick();
	    }
	}

	public void valueChanged(ListSelectionEvent event) {
	    if(collection_list.isSelectionEmpty()) {
		card_layout.show(description_pane, BLANK);
		open_button.setEnabled(false);
	    }
	    else {
		BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration) collection_list.getSelectedValue();
		description_textarea.setText(collection_configuration.getDescription());
		description_textarea.setCaretPosition(0);
		card_layout.show(description_pane, DESCRIPTION);
		open_button.setEnabled(true);
	    }
	}
    }

    // use this if we ever go back to viewing all colls at once
    /*    private class GS3CollectionListModel
	extends AbstractListModel {

	private TreeSet data;

	public GS3CollectionListModel() {
	    data = new TreeSet();
	    File sites_folder = new File(Utility.getSitesDir(Configuration.gsdl3_web_path));
	    File sites[] = sites_folder.listFiles();
	    for (int s=0; s<sites.length; s++) {
		String site_name = sites[s].getName();
		File collect_folder = new File(Utility.getCollectDir(Configuration.gsdl3_web_path, site_name) );
		if (!collect_folder.exists()) {
		    continue;
		}
		File[] collection_folders = collect_folder.listFiles();
		for(int i = 0; i < collection_folders.length; i++) {
		    File collection_folder = collection_folders[i];
		    String collection_foldername = collection_folder.getName();
		    if(!collection_folder.isFile() && !collection_foldername.equals(StaticStrings.MODEL_COLLECTION_NAME)) {
			BasicCollectionConfiguration collection_configuration = new BasicCollectionConfiguration(new File(collection_folder, Utility.CONFIG_FILE), site_name);
			if(!collection_configuration.getName().equals(StaticStrings.ERROR_STR)) {
			    data.add(collection_configuration);
			}
		    }
		    collection_foldername = null;
		    collection_folder = null;
		} // for each collection
		collection_folders = null;
		collect_folder = null;
	    } // for each site
	    sites_folder = null;
	    sites = null;
	}

	public Object getElementAt(int index) {
	    Iterator iterator = data.iterator();
	    for(int i = 0; iterator.hasNext(); i++) {
		Object object = iterator.next();
		if(i == index) {
		    iterator = null;
		    return object;
		}
		object = null;
	    }
	    iterator = null;
	    return null;
	}

	public int getSize() {
	    return data.size();
	}
    }
    */	
    private class CollectionListModel
	extends AbstractListModel {

	private TreeSet data;
	static final public int COLLECT   = 3;

	public CollectionListModel() {
	    data = new TreeSet();
	    reload(Gatherer.getCollectDirectoryPath());
	}

	// to be called when the collection directory has changed
	public void reload(String collectDirectoryPath) {
	    data.clear();
	    File collect_directory = new File(collectDirectoryPath);
	    if (!collect_directory.exists()) {
		collect_directory = null;
		return;
	    }

	    load_collection_configs(data,collect_directory);

	    // list size/contents has changed, this listmodel must notify the 
	    // encapsulating JList, else it won't be able to display longer lists
	    fireContentsChanged(this, 0, data.size()); 
	}


	protected void load_collection_configs(TreeSet data, File collect_directory) {

	    File[] collection_folders = collect_directory.listFiles();

	    for(int i = 0; i < collection_folders.length; i++) {
		File collection_folder = collection_folders[i];
		String collection_foldername = collection_folder.getName();

		if(collection_folder.isDirectory() && !collection_foldername.equals(StaticStrings.MODEL_COLLECTION_NAME)) {
		    
		    // this 'file_name' has already been prefixed by 'etc'
		    String file_name;
		    if (Gatherer.GS3){
			convertToGS3Collection(collection_folder);
			file_name = Utility.CONFIG_GS3_FILE;
		    }else{
			file_name = Utility.CONFIG_FILE;
		    }
		    
		    File config_file = new File(collection_folder, file_name);
		    if (config_file.exists()) {
			BasicCollectionConfiguration collection_configuration = new BasicCollectionConfiguration(config_file);

			// look to see if group set?
			// => if it is, don't add, but recurse to look for child collections in collect-group

			if (collection_configuration.getCollectGroup().equals("true")) {
			    load_collection_configs(data, collection_folder);
			}
			else {
			  // add this collection. We want to allow non gli collections, so add anything that has a config file.
			    // webswing - check whether we are allowed to edit this coll
			    if (Gatherer.isWebswing) {
				if (Gatherer.webswingAuthenticator.canEditCollection(collection_foldername)) {
				    data.add(collection_configuration);
				}
			    }
			    else {
				data.add(collection_configuration);
			    }
			}
		    }
		    config_file = null;
		}
		collection_foldername = null;
		collection_folder = null;
	    }
	    collection_folders = null;
	    collect_directory = null;
	}



	public Object getElementAt(int index) {
	    Iterator iterator = data.iterator();
	    for(int i = 0; iterator.hasNext(); i++) {
		Object object = iterator.next();
		if(i == index) {
		    iterator = null;
		    return object;
		}
		object = null;
	    }
	    iterator = null;
	    return null;
	}

	public int getSize() {
	    return data.size();
	}

	public void convertToGS3Collection(File collection_folder) {

	    File collect_cfg_file = new File(collection_folder.getAbsolutePath() + File.separator + "etc" + File.separator + "collect.cfg");
	    File build_cfg_file = new File(collection_folder.getAbsolutePath() + File.separator+"index" + File.separator + "build.cfg");

	    if (collect_cfg_file.exists() && build_cfg_file.exists()){
		// Generate the convert_coll_from_gs2.pl command
		ArrayList command_parts_list = new ArrayList();
		if (!Gatherer.isGsdlRemote) {
		    command_parts_list.add(Configuration.perl_path);
		    command_parts_list.add("-S");
		}
		command_parts_list.add(Configuration.getGS3ScriptPath() + "convert_coll_from_gs2.pl");
		command_parts_list.add("-collectdir");
		command_parts_list.add(collection_folder.getParent());
		command_parts_list.add(collection_folder.getName());

		// Run the convert_coll_from_gs2.pl command
		String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
		GShell process = new GShell(command_parts, GShell.CONVERT, COLLECT, null, null, GShell.GSHELL_CONVERT);
		//process.addGShellListener(this);
		process.run(); // Don't bother threading this... yet
		
		// From now, won't dangerously delete GS2 collect and build config files anymore
		//collect_cfg_file.delete();
		//build_cfg_file.delete();

		File collect_bak_file = new File(collection_folder.getAbsolutePath() + File.separator + "etc" + File.separator + "collect.cfg.bak");
		File build_bak_file = new File(collection_folder.getAbsolutePath() + File.separator+"index" + File.separator + "build.cfg.bak");
		if(!collect_cfg_file.renameTo(collect_bak_file)) {
		    System.err.println("Unable to move collect.cfg to " + collect_bak_file);
		}
		if(!build_cfg_file.renameTo(build_bak_file)) {
		    System.err.println("Unable to move build.cfg to " + build_bak_file);
		}
	    }
	}
    }

    private class OpenListener
	implements ActionListener {

	public void actionPerformed(ActionEvent event) {
	    result = OK_OPTION;
	    Object selected_object = collection_list.getSelectedValue();
	    if (selected_object instanceof BasicCollectionConfiguration) {
		BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration)selected_object; //(BasicCollectionConfiguration) collection_list.getSelectedValue();
		//****************
		File collect_cfg_file = collection_configuration.getFile(); // returns the collect.cfg file
		result = FormatConversionDialog.checkForGS2FormatStatements(collect_cfg_file);
		if(result == OK_OPTION) { // either there were no gs2 format stmts or user chose to proceed
		    File etc_folder = collect_cfg_file.getParentFile();
		    File collection_folder = etc_folder.getParentFile();
		    filename = collection_folder.getAbsolutePath() + File.separator + "gli.col";
		    collection_folder = null;
		    etc_folder = null;
		    collect_cfg_file = null;
		    collection_configuration = null;
		}
		OpenCollectionDialog.this.dispose();
	    }

	    Gatherer.collectDirectoryHasChanged(Gatherer.getCollectDirectoryPath(), 
				newCollectPath, Gatherer.g_man.getContentPane()); 
	        // will tell the server that the collect directory has changed and that
			// the workspace needs to be refreshed (Documents in Greenstone Collections)

	}
    }
}
