package io.andrewohara.tinkertime.views;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.Arrays;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import org.apache.commons.io.FilenameUtils;
import io.andrewohara.common.Util;
import io.andrewohara.common.content.ImageManager;
import io.andrewohara.common.views.Dialogs;
import io.andrewohara.common.views.UrlLabels;
import io.andrewohara.tinkertime.TinkerTimeLauncher;
import io.andrewohara.tinkertime.controllers.ImportController;
import io.andrewohara.tinkertime.controllers.ModManager;
import io.andrewohara.tinkertime.controllers.ModManager.NoModSelectedException;
import io.andrewohara.tinkertime.io.crawlers.CrawlerFactory;
import io.andrewohara.tinkertime.io.kspLauncher.GameLauncher;
import io.andrewohara.tinkertime.models.ConfigData;
import io.andrewohara.tinkertime.models.mod.Mod;
public class Actions {
// -- Helpers ---------------------------------------------------------
@SuppressWarnings("serial")
public
static abstract class TinkerAction extends AbstractAction {
protected static final ImageManager IMAGE_MANAGER = new ImageManager();;
protected final JComponent parent;
protected final ModManager mm;
private final Dialogs dialogs;
private TinkerAction(String title, String iconName, JComponent parent, ModManager mm, Dialogs dialogs){
super(title, iconName != null ? IMAGE_MANAGER.getIcon(iconName): null);
this.parent = parent;
this.mm = mm;
this.dialogs = dialogs;
putValue(Action.SHORT_DESCRIPTION, title);
}
@Override
public void actionPerformed(ActionEvent evt) {
try {
call();
} catch (Exception e){
dialogs.errorDialog(parent, e);
}
}
public TinkerAction withoutIcon(){
putValue(Action.SMALL_ICON, null);
return this;
}
protected abstract void call() throws Exception;
}
@SuppressWarnings("serial")
private static final class GoToUrlAction extends TinkerAction {
private final URL url;
GoToUrlAction(String title, String url, String iconPath, JComponent parent, Dialogs dialogs) {
super(title, iconPath, parent, null, dialogs);
try {
this.url = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
protected void call() throws Exception {
Util.goToHyperlink(url);
}
}
// -- Actions -----------------------------------------------------------
@SuppressWarnings("serial")
public static class AddModAction extends TinkerAction {
public AddModAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("Add Mod", "icon/glyphicons_432_plus.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
// Get URL from user
String urlString = JOptionPane.showInputDialog(
parent,
"Please enter the URL of the mod you would like to"
+ " add.\ne.g. http://www.curse.com/ksp-mods/kerbal/220221-mechjeb\n\n"
+ "Supported Hosts are " + Arrays.asList(CrawlerFactory.ACCEPTED_MOD_HOSTS),
"Enter Mod Page URL",
JOptionPane.QUESTION_MESSAGE
);
if (urlString == null || urlString.trim().isEmpty()){
return;
}
// Try to add Mod
try {
mm.downloadNewMod(new URL(urlString));
} catch(MalformedURLException ex){
mm.downloadNewMod(new URL("http://" + urlString));
}
}
}
@SuppressWarnings("serial")
public static class DeleteModAction extends TinkerAction {
public DeleteModAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("Delete Mod", "icon/glyphicons_433_minus.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
try {
Mod selectedMod = mm.getSelectedMod();
if (TinkerDialogs.confirmDeleteMod(parent, selectedMod.getName())){
mm.deleteMod(selectedMod);
}
} catch (NoModSelectedException ex){
// Do Nothing
}
}
}
@SuppressWarnings("serial")
public static class UpdateModAction extends TinkerAction {
public UpdateModAction(JComponent parent, ModManager mm, Dialogs dialogs){
this("Update Mod", parent, mm, dialogs);
}
private UpdateModAction(String title, JComponent parent, ModManager mm, Dialogs dialogs){
super(title, "icon/glyphicons_181_download_alt.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
try {
mm.updateMod(mm.getSelectedMod(), true);
} catch (NoModSelectedException ex){
// Do Nothing
}
}
}
@SuppressWarnings("serial")
public static class UpdateAllAction extends UpdateModAction {
public UpdateAllAction(JComponent parent, ModManager mm, Dialogs dialogs) {
super("Update All", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
mm.updateMods();
}
}
@SuppressWarnings("serial")
public static class CheckforUpdatesAction extends TinkerAction {
public CheckforUpdatesAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("Check for Mod Updates", "icon/glyphicons_027_search.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
mm.checkForModUpdates();
}
}
@SuppressWarnings("serial")
public static class EnableDisableModAction extends TinkerAction {
public EnableDisableModAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("Enable/Disable", "icon/glyphicons_457_transfer.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
try {
mm.toggleMod(mm.getSelectedMod());
} catch (NoModSelectedException ex){
// Do Nothing
}
}
}
public static TinkerAction newHelpAction(JComponent parent, Dialogs dialogs){
return new GoToUrlAction(
"Help",
"https://github.com/oharaandrew314/TinkerTime/wiki",
"icon/glyphicons_194_circle_question_mark.png",
parent,
dialogs
);
}
public static TinkerAction newWebsiteAction(JComponent parent, Dialogs dialogs){
return new GoToUrlAction("Website", "http://andrewohara.io/TinkerTime", null, parent, dialogs);
}
@SuppressWarnings("serial")
public static class AboutAction extends TinkerAction {
public AboutAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("About", "icon/glyphicons_003_user.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
Object[] message = {
TinkerTimeLauncher.FULL_NAME,
"\n",
"This work is licensed under the GNU GPL v3.0 License\n",
new UrlLabels.UrlLink("View a copy of this license", new URL("http://opensource.org/licenses/gpl-3.0")).getComponent(),
"\n",
TinkerTimeLauncher.NAME + " uses Glyphicons (glyphicons.com)",
"\n",
new UrlLabels.UrlLink(TinkerTimeLauncher.NAME + " Website", new URL("http://andrewohara.io/TinkerTime")).getComponent(),
};
JOptionPane.showMessageDialog(
parent,
message,
"About " + TinkerTimeLauncher.NAME,
JOptionPane.INFORMATION_MESSAGE,
IMAGE_MANAGER.getIcon("icon/app/icon 128x128.png")
);
}
}
@SuppressWarnings("serial")
public static class ContactAction extends TinkerAction {
public ContactAction(JComponent parent, ModManager mm, Dialogs dialogs){
super("Contact Me", "icon/glyphicons_010_envelope.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
Desktop desktop = Desktop.getDesktop();
String message = "mailto:tinkertime@andrewohara.io?subject=TinkerTime%20Support%20Request";
URI uri = URI.create(message);
desktop.mail(uri);
}
}
@SuppressWarnings("serial")
public static class ExportMods extends TinkerAction {
private final ImportController importController;
private static final String ALL = "Export All Mods", ENABLED = "Export Enabled Mods";
public ExportMods(JComponent parent, ImportController importController, Dialogs dialogs){
super("Export Mods", "icon/glyphicons_359_file_export.png", parent, null, dialogs);
this.importController = importController;
}
@Override
protected void call() throws Exception {
Object result = JOptionPane.showInputDialog(
parent, "Which mods would you like to export?",
"Export Mods", JOptionPane.QUESTION_MESSAGE, null,
new String[] { ALL, ENABLED }, ALL);
boolean enabledOnly = true;
if (result == null){
return;
} else if (result.equals(ALL)){
enabledOnly = false;
}
// Set default file extension if not set
Path exportPath = FileChoosers.chooseImportExportFile(true);
if (FilenameUtils.getExtension(exportPath.toString()).isEmpty()){
exportPath = Paths.get(exportPath.toString() + ".txt");
}
int exported = importController.exportMods(exportPath, enabledOnly);
JOptionPane.showMessageDialog(
parent,
String.format("%d Mods have been exported.", exported),
"Exported",
JOptionPane.INFORMATION_MESSAGE
);
}
}
@SuppressWarnings("serial")
public static class ImportMods extends TinkerAction {
private final ImportController importController;
public ImportMods(JComponent parent, ImportController importController, Dialogs dialogs){
super("Import Mods", "icon/glyphicons-359-file-import.png", parent, null, dialogs);
this.importController = importController;
}
@Override
protected void call() throws Exception {
int imported = importController.importMods(FileChoosers.chooseImportExportFile(false));
JOptionPane.showMessageDialog(
parent,
String.format("%d Mod(s) have been imported.", imported),
"Imported",
JOptionPane.INFORMATION_MESSAGE
);
}
}
@SuppressWarnings("serial")
public static class UpdateTinkerTime extends TinkerAction {
public UpdateTinkerTime(JComponent parent, ModManager mm, Dialogs dialogs){
super("Check for Tinker Time Update", null, parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
mm.tryUpdateModManager();
}
}
@SuppressWarnings("serial")
public static class AddModZip extends TinkerAction {
public AddModZip(JComponent parent, ModManager mm, Dialogs dialogs){
super("Add Mod from Zip File", "icon/glyphicons_410_compressed.png", parent, mm, dialogs);
}
@Override
protected void call() throws Exception {
try {
mm.addModZip(FileChoosers.chooseModZip());
} catch (FileNotFoundException e){
// Do nothing if file was not chosen
}
}
}
@SuppressWarnings("serial")
public static class LaunchKspAction extends TinkerAction {
private final GameLauncher launcher;
public LaunchKspAction(JComponent parent, ModManager mm, GameLauncher launcher, Dialogs dialogs){
super("Launch KSP", "icon/rocket.png", parent, mm, dialogs);
this.launcher = launcher;
}
@Override
protected void call() throws Exception {
launcher.launchGame();
}
}
@SuppressWarnings("serial")
public static class OpenGameDataFolder extends TinkerAction {
private final ConfigData config;
public OpenGameDataFolder(JComponent parent, ModManager mm, ConfigData config, Dialogs dialogs) {
super("Open GameData Folder", "icon/glyphicons_144_folder_open.png", parent, mm, dialogs);
this.config = config;
}
@Override
protected void call() throws Exception {
Desktop.getDesktop().open(config.getSelectedInstallation().getGameDataPath().toFile());
}
}
@SuppressWarnings("serial")
public static class LaunchInstallationSelector extends TinkerAction {
private final InstallationSelectorView selector;
public LaunchInstallationSelector(JComponent parent, ModManager mm, InstallationSelectorView selector, Dialogs dialogs) {
super("Select KSP Installation", "icon/glyphicons_342_hdd.png", parent, mm, dialogs);
this.selector = selector;
}
@Override
protected void call() throws Exception {
selector.toDialog();
}
}
//////////////////////////////
// Options Action Listeners //
//////////////////////////////
public static class CheckForAppUpdatesAction implements ActionListener {
private final JCheckBox checkBox;
private final ConfigData config;
private final Dialogs dialogs;
public CheckForAppUpdatesAction(JCheckBox checkBox, ConfigData config, Dialogs dialogs){
this.checkBox = checkBox;
this.config = config;
this.dialogs = dialogs;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
config.setCheckForAppUpdatesOnStartup(checkBox.isSelected());
} catch (SQLException e1) {
dialogs.errorDialog(checkBox, e1);
}
}
}
public static class CheckForModUpdatesAction implements ActionListener {
private final JCheckBox checkBox;
private final ConfigData config;
private final Dialogs dialogs;
public CheckForModUpdatesAction(JCheckBox checkBox, ConfigData config, Dialogs dialogs){
this.checkBox = checkBox;
this.config = config;
this.dialogs = dialogs;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
config.setCheckForModUpdatesOnStartup(checkBox.isSelected());
} catch (SQLException e1) {
dialogs.errorDialog(checkBox, e1);
}
}
}
@SuppressWarnings("serial")
public static class UpdateLaunchArgsAction extends AbstractAction {
private final ConfigData config;
private final Dialogs dialogs;
public UpdateLaunchArgsAction(ConfigData config, Dialogs dialogs){
super("KSP Launch Args");
this.config = config;
this.dialogs = dialogs;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
String curArgs = config.getLaunchArguments();
String newArgs = JOptionPane.showInputDialog(null, "Modify the Launch Args for KSP", curArgs);
if (newArgs != null && !newArgs.equals(curArgs)){
config.setLaunchArguments(newArgs);
}
} catch (SQLException e1){
dialogs.errorDialog(null, "Error updating KSP Launch Args", e1);
}
}
}
}