package moviescraper.doctord.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import moviescraper.doctord.controller.UtilityFunctions;
import moviescraper.doctord.controller.amalgamation.AllAmalgamationOrderingPreferences;
import moviescraper.doctord.controller.amalgamation.DataItemSourceAmalgamationPreference;
import moviescraper.doctord.controller.amalgamation.ScraperGroupAmalgamationPreference;
import moviescraper.doctord.controller.siteparsingprofile.SiteParsingProfile.ScraperGroupName;
import moviescraper.doctord.model.dataitem.DataItemSource;
import moviescraper.doctord.view.renderer.DataItemSourceRenderer;
import moviescraper.doctord.view.renderer.MovieFieldCellRenderer;
public class AmalgamationSettingsDialog {
//Begin View Objects
private JPanel panel;
JPanel overallAmalgamationPreferencePanel;
JPanel specificAmalgamationPreferencePanel;
private GUIMain guiMain;
private JComboBox<ScraperGroupName> scraperGroupNameComboBox;
private JList<DataItemSource> overallAmalgamationPreferenceList;
private JList<DataItemSource> specificFieldAmalgamationPreferenceList;
JList<Field> jListMovieFields;
//Buttons to reorder ParsingProfiles or disable them
JButton upButtonOverall;
JButton downButtonOverall;
JButton disableButtonOverall;
JButton upButtonSpecific;
JButton downButtonSpecific;
JButton disableButtonSpecific;
JButton useDefaultOrderingForSelectedItem;
JButton resetToDefaultSettings;
JLabel panelHeaderSpecificFieldAmalgamationPreference;
private static final int layoutVerticalGap = 10;
private static final int layoutHorizontalGap = 10;
//End View Objects
//Model objects
AllAmalgamationOrderingPreferences amalgamationPreferences; //state of our choices stored here when outside this dialog
AllAmalgamationOrderingPreferences amalgamationPreferencesOriginal; //restore us to original state of our object before opening this dialog if we hit cancel
private DefaultListModel<DataItemSource> overallAmalgamationPreferenceListModel;
private DefaultListModel<DataItemSource> specificFieldAmalgamationPreferenceListModel;
private DefaultListModel<Field> movieFieldsListModel;
Field selectedMovieField;
public AmalgamationSettingsDialog(GUIMain parent, AllAmalgamationOrderingPreferences amalgamationPreferences) {
this.guiMain = parent;
BorderLayout panelLayoutManager = new BorderLayout();
panelLayoutManager.setHgap(layoutHorizontalGap);
panelLayoutManager.setVgap(layoutVerticalGap);
this.panel = new JPanel(panelLayoutManager);
this.amalgamationPreferences = amalgamationPreferences;
this.amalgamationPreferencesOriginal = (AllAmalgamationOrderingPreferences) UtilityFunctions.cloneObject(this.amalgamationPreferences);
panelHeaderSpecificFieldAmalgamationPreference = new JLabel("Specific Field", SwingConstants.CENTER);
//Begin Scraper Groups
scraperGroupNameComboBox = createScraperGroupDropDown();
BorderLayout northPanelLayoutManager = new BorderLayout();
northPanelLayoutManager.setVgap(layoutVerticalGap);
JPanel northPanel = new JPanel(northPanelLayoutManager);
JLabel helpMessage = new JLabel("<html>Select the scrapers you wish to use and the preferred order of each item to use when amalgamating data from the same scraping group.<br>Higher numbered items have precedence over lower numbered items.<br> Any scrapers disabled under \"Default Ordering\" will not scrape at all, even if enabled in the specific ordering section.</html>");
northPanel.add(helpMessage, BorderLayout.SOUTH);
JPanel scraperGroupNameComboPanel = new JPanel();
scraperGroupNameComboPanel.add(new JLabel("Scraper Group:"));
scraperGroupNameComboPanel.add(scraperGroupNameComboBox);
northPanel.add(scraperGroupNameComboPanel, BorderLayout.NORTH);
panel.add(northPanel, BorderLayout.NORTH);
//End Scraper Groups
//Movie Field Panel Initialization
JList<Field> allowedMovieFieldsList = createMovieFieldsList();
jListMovieFields.setSelectedIndex(0);
JScrollPane movieFieldsScrollPane = new JScrollPane(allowedMovieFieldsList);
JPanel movieFieldPanel = new JPanel(new BorderLayout());
movieFieldPanel.add(movieFieldsScrollPane);
//Movie Field Panel End
//Overall Amalgamation Preferences Panel Begin
overallAmalgamationPreferenceList = createOverallAmalgamationPreferenceList();
JScrollPane overallAmalgamationPreferenceScrollPane = new JScrollPane(overallAmalgamationPreferenceList);
overallAmalgamationPreferencePanel = new JPanel(new BorderLayout());
overallAmalgamationPreferencePanel.setPreferredSize(new Dimension(300,200));
overallAmalgamationPreferencePanel.add(overallAmalgamationPreferenceScrollPane, BorderLayout.CENTER);
Box upDownDisablePanel = Box.createVerticalBox();
upButtonOverall = createUpButton(overallAmalgamationPreferenceList, overallAmalgamationPreferenceListModel, true);
disableButtonOverall = createDisableButton(overallAmalgamationPreferenceList, overallAmalgamationPreferenceListModel, true);
downButtonOverall = createDownButton(overallAmalgamationPreferenceList, overallAmalgamationPreferenceListModel, true);
upDownDisablePanel.add(upButtonOverall);
upDownDisablePanel.add(disableButtonOverall);
upDownDisablePanel.add(downButtonOverall);
overallAmalgamationPreferencePanel.add(upDownDisablePanel, BorderLayout.EAST);
overallAmalgamationPreferencePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), "Default Ordering",TitledBorder.CENTER, TitledBorder.TOP));
panel.add(overallAmalgamationPreferencePanel, BorderLayout.WEST);
//Scraper Panel End
//Specific Scraper Field Panel Begin
specificFieldAmalgamationPreferenceList = createSpecificFieldAmalgamationPreferenceList();
JScrollPane specificFieldScraperScrollPane = new JScrollPane(specificFieldAmalgamationPreferenceList);
specificAmalgamationPreferencePanel = new JPanel(new BorderLayout());
specificAmalgamationPreferencePanel.setPreferredSize(new Dimension(300,200));
specificAmalgamationPreferencePanel.add(specificFieldScraperScrollPane, BorderLayout.CENTER);
Box upDownDisablePanelSpecific = Box.createVerticalBox();
upButtonSpecific = createUpButton(specificFieldAmalgamationPreferenceList, specificFieldAmalgamationPreferenceListModel, false);
disableButtonSpecific = createDisableButton(specificFieldAmalgamationPreferenceList, specificFieldAmalgamationPreferenceListModel, false);
downButtonSpecific = createDownButton(specificFieldAmalgamationPreferenceList, specificFieldAmalgamationPreferenceListModel, false);
useDefaultOrderingForSelectedItem = useDefaultOrderingForSelectedItemButton();
upDownDisablePanelSpecific.add(upButtonSpecific);
upDownDisablePanelSpecific.add(disableButtonSpecific);
upDownDisablePanelSpecific.add(downButtonSpecific);
upDownDisablePanelSpecific.add(useDefaultOrderingForSelectedItem);
specificAmalgamationPreferencePanel.add(upDownDisablePanelSpecific, BorderLayout.EAST);
JPanel allSpecificFieldPanels = new JPanel(new BorderLayout());
allSpecificFieldPanels.add(panelHeaderSpecificFieldAmalgamationPreference,BorderLayout.NORTH);
allSpecificFieldPanels.add(movieFieldPanel, BorderLayout.WEST);
allSpecificFieldPanels.add(specificAmalgamationPreferencePanel, BorderLayout.EAST);
allSpecificFieldPanels.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), "Specific Ordering",TitledBorder.CENTER, TitledBorder.TOP));
panel.add(allSpecificFieldPanels, BorderLayout.EAST);
//Specific Scraper Field Panel End
resetToDefaultSettings = createResetDefaultSettingsButton();
panel.add(resetToDefaultSettings, BorderLayout.SOUTH);
//JLabel helpLabel = new JLabel("<html>Any scrapers selected here will be used to amalgamate data when using either the<br> \"Scrape JAV\" or \"Scrape JAV (Automatic)\" scrapers</html>");
//panel.add(helpLabel);
/*for (String option : options) {
boolean isSelected = selected.contains(option);
JCheckBox cb = new JCheckBox(option, isSelected);
checkboxes.add(cb);
panel.add(cb);
}*/
}
private JButton useDefaultOrderingForSelectedItemButton() {
JButton button = new JButton("Use Default Ordering");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox.getSelectedItem()).removeCustomOrderingForField(selectedMovieField);
createSpecificFieldAmalgamationPreferenceList();
}
});
return button;
}
private JButton createResetDefaultSettingsButton() {
resetToDefaultSettings = new JButton("Reset All To Default Settings");
resetToDefaultSettings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
amalgamationPreferences.reinitializeDefaultPreferences();
createOverallAmalgamationPreferenceList();
createSpecificFieldAmalgamationPreferenceList();
}
});
return resetToDefaultSettings;
}
private void synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(final DefaultListModel<DataItemSource> amalgamationPreferenceListModel, boolean isOverallPrefSync)
{
if(amalgamationPreferenceListModel != null)
{
LinkedList<DataItemSource> sppiAllValues = new LinkedList<>();
for(int i = 0; i < amalgamationPreferenceListModel.getSize(); i++)
{
sppiAllValues.add(amalgamationPreferenceListModel.get(i));
}
if(isOverallPrefSync)
{
DataItemSourceAmalgamationPreference overallAmalgamationPreference = amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox.getSelectedItem()).getOverallAmalgamationPreference();
overallAmalgamationPreference.setAmalgamationPreferenceOrder(sppiAllValues);
}
else
{
DataItemSourceAmalgamationPreference preferenceToSet = new DataItemSourceAmalgamationPreference(sppiAllValues);
amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox
.getSelectedItem()).setCustomOrderingForField(selectedMovieField, preferenceToSet);
panelHeaderSpecificFieldAmalgamationPreference.setText("<html> Using <b>Specific</b> Ordering for " + getNameOfCurrentMovieFieldSelected() + "</html>");
}
}
}
private void swapElements(final JList<DataItemSource> amalgamationPreferenceList,
final DefaultListModel<DataItemSource> amalgamationPreferenceListModel, boolean isOverallPrefSync, int pos1, int pos2) {
DataItemSource tmp = (DataItemSource) amalgamationPreferenceListModel.get(pos1);
amalgamationPreferenceListModel.set(pos1, amalgamationPreferenceListModel.get(pos2));
amalgamationPreferenceListModel.set(pos2, tmp);
synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(amalgamationPreferenceListModel, isOverallPrefSync);
}
private JButton createUpButton(
final JList<DataItemSource> amalgamationPreferenceList,
final DefaultListModel<DataItemSource> amalgamationPreferenceListModel, final boolean isOverallPrefSync) {
JButton upButton = new JButton("↑");
upButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int indexOfSelected = amalgamationPreferenceList.getSelectedIndex();
if(indexOfSelected > 0 && indexOfSelected != amalgamationPreferenceListModel.getSize() - 1)
{
swapElements(amalgamationPreferenceList,
amalgamationPreferenceListModel, isOverallPrefSync, indexOfSelected,
indexOfSelected - 1);
indexOfSelected = indexOfSelected - 1;
amalgamationPreferenceList.setSelectedIndex(indexOfSelected );
amalgamationPreferenceList.updateUI();
}
}
});
return upButton;
}
private JButton createDownButton(final JList<DataItemSource> amalgamationPreferenceList,
final DefaultListModel<DataItemSource> amalgamationPreferenceListModel, final boolean isOverallPrefSync)
{
JButton downButton = new JButton("↓");
downButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int indexOfSelected = amalgamationPreferenceList.getSelectedIndex();
//We don't want to be able to move either the last item in the list or the one before that down
//this is because the last item in the list is always the default item, and we always want that to be last
if(indexOfSelected >= 0 && indexOfSelected < amalgamationPreferenceListModel.getSize() - 2)
{
swapElements(amalgamationPreferenceList,
amalgamationPreferenceListModel, isOverallPrefSync, indexOfSelected,
indexOfSelected + 1);
indexOfSelected = indexOfSelected + 1;
amalgamationPreferenceList.setSelectedIndex(indexOfSelected );
amalgamationPreferenceList.updateUI();
}
}
});
return downButton;
}
private JButton createDisableButton(final JList<DataItemSource> amalgamationPreferenceList,
final DefaultListModel<DataItemSource> amalgamationPreferenceListModel, final boolean isOverallPrefSync)
{
JButton disableButton = new JButton("<html><font color='green'>Enable</font> / <font color='red'><strike>Disable</strike></font></html>");
disableButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DataItemSource selectedItem = amalgamationPreferenceList.getSelectedValue();
if(selectedItem != null){
selectedItem.setDisabled(!selectedItem.isDisabled());
synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(amalgamationPreferenceListModel, isOverallPrefSync);
amalgamationPreferenceList.updateUI();
}
}
});
return disableButton;
}
private JComboBox<ScraperGroupName> createScraperGroupDropDown()
{
//Get any scraper groups defined except for items belonging to the default set
EnumSet<ScraperGroupName> everythingButDefaultGroup = EnumSet
.complementOf(EnumSet
.of(ScraperGroupName.DEFAULT_SCRAPER_GROUP));
JComboBox<ScraperGroupName> comboBox = new JComboBox<>(
everythingButDefaultGroup
.toArray(new ScraperGroupName[everythingButDefaultGroup
.size()]));
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createOverallAmalgamationPreferenceList();
synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(overallAmalgamationPreferenceListModel, true);
overallAmalgamationPreferenceList.updateUI();
createSpecificFieldAmalgamationPreferenceList();
synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(specificFieldAmalgamationPreferenceListModel, false);
specificFieldAmalgamationPreferenceList.updateUI();
}
});
return comboBox;
}
private JList<DataItemSource> createOverallAmalgamationPreferenceList()
{
if(overallAmalgamationPreferenceListModel == null)
overallAmalgamationPreferenceListModel = new DefaultListModel<>();
else
overallAmalgamationPreferenceListModel.clear();
if(overallAmalgamationPreferenceList == null)
{
overallAmalgamationPreferenceList = new JList<>(overallAmalgamationPreferenceListModel);
overallAmalgamationPreferenceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
overallAmalgamationPreferenceList.setCellRenderer(new DataItemSourceRenderer());
}
Collection<DataItemSource> listData = amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox.getSelectedItem()).getOverallAmalgamationPreference().getAmalgamationPreferenceOrder();
for(DataItemSource currentItem : listData)
{
overallAmalgamationPreferenceListModel.addElement(currentItem);
}
synchronizeAmalgamationPreferenceListToDataItemSourceAmalgamationPreference(overallAmalgamationPreferenceListModel, true);
return overallAmalgamationPreferenceList;
}
private JList<DataItemSource> createSpecificFieldAmalgamationPreferenceList()
{
if(specificFieldAmalgamationPreferenceListModel == null)
{
specificFieldAmalgamationPreferenceListModel = new DefaultListModel<>();
}
else
{
specificFieldAmalgamationPreferenceListModel.clear();
}
//case when no item is selected
if(selectedMovieField == null)
{
specificFieldAmalgamationPreferenceListModel.clear();
panelHeaderSpecificFieldAmalgamationPreference.setText("No movie field selected.");
specificFieldAmalgamationPreferenceList.updateUI();
return specificFieldAmalgamationPreferenceList;
}
if(jListMovieFields == null)
jListMovieFields = createMovieFieldsList();
if(specificFieldAmalgamationPreferenceList == null)
{
specificFieldAmalgamationPreferenceList = new JList<>(specificFieldAmalgamationPreferenceListModel);
specificFieldAmalgamationPreferenceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
specificFieldAmalgamationPreferenceList.setCellRenderer(new DataItemSourceRenderer());
}
Collection<DataItemSource> listData;
DataItemSourceAmalgamationPreference orderingForField = amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox.getSelectedItem()).getSpecificAmalgamationPreference(selectedMovieField);
if(orderingForField != null)
{
panelHeaderSpecificFieldAmalgamationPreference.setText("<html> Using <b>Specific</b> Ordering for " + getNameOfCurrentMovieFieldSelected() + "</html>");
listData = orderingForField.getAmalgamationPreferenceOrder();
}
else
{
panelHeaderSpecificFieldAmalgamationPreference.setText("<html>Using <b>Default</b> Ordering for " + getNameOfCurrentMovieFieldSelected() + "</html>");
//we need to create a new object for this field copied from the overall ordering using the same type as the original items
listData = new LinkedList<>();
DataItemSourceAmalgamationPreference overallPrefs = amalgamationPreferences.getScraperGroupAmalgamationPreference((ScraperGroupName) scraperGroupNameComboBox.getSelectedItem()).getOverallAmalgamationPreference();
LinkedList<DataItemSource> overallPrefsDataItems = overallPrefs.getAmalgamationPreferenceOrder();
for(DataItemSource currentItem : overallPrefsDataItems)
{
listData.add(currentItem.createInstanceOfSameType());
}
}
for(DataItemSource currentItem : listData)
{
specificFieldAmalgamationPreferenceListModel.addElement(currentItem);
}
specificFieldAmalgamationPreferenceList.updateUI();
return specificFieldAmalgamationPreferenceList;
}
private String getNameOfCurrentMovieFieldSelected()
{
if(selectedMovieField == null)
return "";
else return MovieFieldCellRenderer.formatFieldText(selectedMovieField.getName());
}
private JList<Field> createMovieFieldsList()
{
movieFieldsListModel = new DefaultListModel<>();
List<Field> listData = ScraperGroupAmalgamationPreference.getMoviefieldNames();
for(Field currentField : listData)
movieFieldsListModel.addElement(currentField);
jListMovieFields = new JList<>(movieFieldsListModel);
jListMovieFields.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jListMovieFields.addListSelectionListener(new ListSelectionListener() {
@SuppressWarnings("unchecked")
@Override
public void valueChanged(ListSelectionEvent e) {
//no item selected
if (((JList<Field>) e.getSource()).getSelectedIndex() == -1)
{
selectedMovieField = null;
createSpecificFieldAmalgamationPreferenceList();
specificFieldAmalgamationPreferenceList.updateUI();
}
Field newSelectedField = ((JList<Field>) e.getSource()).getSelectedValue();
if(newSelectedField != null && !newSelectedField.equals(selectedMovieField))
{
selectedMovieField = newSelectedField;
createSpecificFieldAmalgamationPreferenceList();
specificFieldAmalgamationPreferenceList.updateUI();
//updateSpecificFieldAmalgamationLists(selectedMovieField);
}
}
});
jListMovieFields.setCellRenderer(new MovieFieldCellRenderer());
selectedMovieField = jListMovieFields.getSelectedValue();
return jListMovieFields;
}
private void restorePreferencesBeforeDialogOpened()
{
amalgamationPreferences.setAllAmalgamationOrderingPreferences(amalgamationPreferencesOriginal.getAllAmalgamationOrderingPreferences());
}
public boolean show(){
JFrame parentFrame = null;
if(guiMain != null)
parentFrame = guiMain.getFrmMoviescraper();
int result = JOptionPane.showOptionDialog(parentFrame, panel, "Amalgamation Settings", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if (result == JOptionPane.OK_OPTION) {
amalgamationPreferences.saveToPreferencesFile();
guiMain.reinitializeAmalgamationPreferencesFromFile();
return true;
}
else //hit cancel, undo our changes
{
restorePreferencesBeforeDialogOpened();
return false;
}
}
}