package com.illumina.basespace.igv;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jnlp.ServiceManager;
import javax.jnlp.SingleInstanceListener;
import javax.jnlp.SingleInstanceService;
import javax.jnlp.UnavailableServiceException;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.broad.igv.ui.IGV;
import org.broad.igv.ui.Main;
import org.broad.igv.ui.UIConstants;
import org.broad.igv.ui.action.MenuAction;
import org.broad.igv.ui.event.ViewChange;
import org.broad.igv.ui.panel.FrameManager;
import org.broad.igv.util.StringUtils;
import com.google.common.eventbus.Subscribe;
import com.illumina.basespace.ApiClient;
import com.illumina.basespace.ApiClientManager;
import com.illumina.basespace.ApiConfiguration;
import com.illumina.basespace.entity.AppResultCompact;
import com.illumina.basespace.entity.FileCompact;
import com.illumina.basespace.igv.session.BaseSpaceOpenSessionMenuAction;
import com.illumina.basespace.igv.session.BaseSpaceSaveSessionMenuAction;
import com.illumina.basespace.igv.ui.BaseSpaceHelper;
import com.illumina.basespace.igv.ui.tree.BrowserDialog;
import com.illumina.basespace.igv.ui.tree.UserNode;
import com.illumina.basespace.igv.vcf.BaseSpaceVariantSetApiFeatureReader;
import com.illumina.basespace.infrastructure.BaseSpaceException;
import com.illumina.basespace.param.FileParams;
import com.illumina.basespace.response.ListFilesResponse;
import com.illumina.basespace.util.BrowserLaunch;
/**
*
* @author bking
*
*/
public class BaseSpaceMain extends Main implements SingleInstanceListener
{
private SingleInstanceService singleInstanceServer;
public static Logger logger = Logger.getLogger(BaseSpaceMain.class.getPackage().getName());
private Map<UUID, ClientContext> clients = new Hashtable<UUID, ClientContext>();
private static BaseSpaceMain instance;
private final static Object lock = new Object();
private JMenu baseSpaceMenu;
private JCheckBoxMenuItem logApiMenu;
private static Logger connectionLogger;
static
{
connectionLogger = Logger.getLogger(ApiClient.class.getPackage().getName());
ConsoleHandler consoleHandler = new ConsoleHandler();
connectionLogger.addHandler(consoleHandler);
connectionLogger.setUseParentHandlers(false);
}
private BaseSpaceMain()
{
try
{
singleInstanceServer = (SingleInstanceService) ServiceManager.lookup("javax.jnlp.SingleInstanceService");
singleInstanceServer.addSingleInstanceListener(this);
}
catch (UnavailableServiceException e)
{
logger.warning("Single instance service not available");
}
baseSpaceMenu = new JMenu("BaseSpace");
IGV.getRootPane().getJMenuBar().add(baseSpaceMenu, IGV.getRootPane().getJMenuBar().getMenuCount() - 1);
JMenuItem mnuDocumentation = new JMenuItem("BaseSpace IGV Documentation");
mnuDocumentation.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
BrowserLaunch.openURL("https://github.com/basespace/basespace-igv/wiki/BaseSpace-IGV-Documentation");
}
});
baseSpaceMenu.add(mnuDocumentation);
JMenuItem mnuBrowser = new JMenuItem("Launch Browser");
mnuBrowser.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
showBrowser();
}
});
baseSpaceMenu.add(mnuBrowser);
logApiMenu = new JCheckBoxMenuItem("Debug Mode");
logApiMenu.setSelected(false);
logApiMenu.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
setDebug(logApiMenu.isSelected());
}
});
baseSpaceMenu.add(logApiMenu);
baseSpaceMenu.addSeparator();
JMenuItem miAbout = new JMenuItem("About...");
miAbout.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0)
{
AboutDialog dlgAbout = new AboutDialog();
dlgAbout.setLocationRelativeTo(IGV.getMainFrame());
dlgAbout.setVisible(true);
}
});
baseSpaceMenu.add(miAbout);
}
protected void setDebug(boolean debug)
{
Level level = debug ? Level.ALL : Level.INFO;
for (Handler handler : connectionLogger.getHandlers())
{
handler.setLevel(level);
}
connectionLogger.setLevel(level);
}
public static BaseSpaceMain instance()
{
if (instance != null) return instance;
synchronized (lock)
{
instance = new BaseSpaceMain();
}
return instance;
}
public static void main(String[] args)
{
String[] baseSpaceArgs = BaseSpaceConfiguration.extractBaseSpaceArgs(args);
String[] baseSpaceArgsWithGenome = new String[baseSpaceArgs.length + 2];
System.arraycopy(baseSpaceArgs, 0, baseSpaceArgsWithGenome, 0, baseSpaceArgs.length);
baseSpaceArgsWithGenome[baseSpaceArgs.length] = "-g";
baseSpaceArgsWithGenome[baseSpaceArgs.length + 1] = "hg19";
Main.main(BaseSpaceConfiguration.removeBaseSpaceArgs(baseSpaceArgsWithGenome));
IGV.getInstance().setTrackLoader(new BaseSpaceTrackLoader());
instance().createBaseSpaceClient(baseSpaceArgs);
}
@Override
public void newActivation(String[] args)
{
logger.info("Handling new webstart activation");
createBaseSpaceClient(BaseSpaceConfiguration.extractBaseSpaceArgs(args));
}
public ApiClient getApiClient(UUID id)
{
return clients.get(id).getApiClient();
}
/**
* Do not show access token in log.
* @param args
*/
public void createBaseSpaceClient(String[] args)
{
if (args == null || args.length == 0)
{
throw new Error("No startup arguments Provided to IGV");
}
logger.info("Create BaseSpace Client with args:");
int index = 0;
for (String arg : args)
{
if(arg.indexOf("token") < 0)
logger.info("\t[" + (++index) + "]=" + arg);
}
final BaseSpaceConfiguration config = BaseSpaceConfiguration.create(args);
ApiConfiguration apiConfig = config.getApiConfiguration();
final ApiClient client = ApiClientManager.instance().createClient(apiConfig);
final UUID id = UUID.randomUUID();
clients.put(id, new ClientContext(client, config));
String appResultId = config.getProperty(BaseSpaceConfiguration.APPRESULT_ID);
if (appResultId != null)
{
AppResultCompact appResult = new AppResultCompact(appResultId);
FileParams fileParams = new FileParams(BaseSpaceConstants.FILE_TYPES.keySet().toArray(new String[0]), 10);
ListFilesResponse resp = client.getFiles(appResult, fileParams);
BaseSpaceTrackLoader.loadTracks(id, resp);
}
// Load passed-in file ids
String fileIdsValue = config.getProperty(BaseSpaceConfiguration.FILE_ID);
if (fileIdsValue != null)
{
List<FileCompact> files = new ArrayList<FileCompact>();
String[] fileIds = fileIdsValue.split(",");
for (String fileId : fileIds)
{
try
{
files.add(client.getFile(fileId).get());
}
catch (Throwable t)
{
BaseSpaceHelper.showErrorDialog(IGV.getMainFrame(), t);
}
}
BaseSpaceTrackLoader.loadTracks(id, files);
}
String debug = config.getProperty(BaseSpaceConfiguration.DEBUG);
if (debug != null)
{
logApiMenu.setSelected(Boolean.parseBoolean(debug));
setDebug(Boolean.parseBoolean(debug));
}
launchBrowser(id);
}
protected void launchBrowser(final UUID id)
{
try
{
ApiClient client = clients.get(id).getApiClient();
UserNode userNode = new UserNode(client.getCurrentUser().get(), id, clients.get(id));
BrowserDialog.instance().getBrowserPanel().addUserNode(userNode);
}
catch (BaseSpaceException bse)
{
BaseSpaceHelper.showErrorDialog(IGV.getMainFrame(), bse);
}
showBrowser();
}
protected void showBrowser()
{
BrowserDialog dialog = BrowserDialog.instance();
dialog.setLocationRelativeTo(IGV.getMainFrame());
dialog.setVisible(true);
dialog.toFront();
}
public JMenu getBaseSpaceMenu()
{
return baseSpaceMenu;
}
public class ClientContext
{
private ApiClient client;
private BaseSpaceConfiguration config;
private long createTime;
public ClientContext(ApiClient client, BaseSpaceConfiguration config)
{
super();
this.client = client;
this.config = config;
this.createTime = System.currentTimeMillis();
}
public ApiClient getApiClient()
{
return client;
}
public BaseSpaceConfiguration getConfig()
{
return config;
}
public long getCreateTime()
{
return createTime;
}
}
}