package com.opentrafficsimulation.editor.light;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Arrays;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.opentrafficsimulation.connector.Connector;
import com.opentrafficsimulation.connector.utility.ConnectorType;
import com.opentrafficsimulation.editor.road.RoadEditor;
import com.opentrafficsimulation.gui.CreateMapFrame;
import com.opentrafficsimulation.gui.CreateSimulationFrame;
import com.opentrafficsimulation.screen.simulation.SimulationScreen;
import com.opentrafficsimulation.utility.constants.AppConstants;
public class LightEditor extends JPanel {
private static final long serialVersionUID = 6332204531497511846L;
// Singleton instance
private static LightEditor lightEditor = new LightEditor();
// Content wrapper
private JScrollPane scrollPane;
private JPanel content = new JPanel();
//private String networkFile = new Connector(ConnectorType.CONNECTOR_NETGENERATE).getInputDir() + "hello.net.xml";
public String networkFile; // Added by mahmut on 10.03.13
public static Integer PORT_NUMBER = 5443; // Added by mahmut on 11.03.13
//public int PORT_NUMBER;
public DefaultListModel junctionModel = new DefaultListModel();
private JList junctionList = new JList(junctionModel);
public DefaultListModel tlModel = new DefaultListModel();
private JList tlList = new JList(tlModel);
public List<String> trafficLightIDs; // Added by mahmut on 11.03.13
public boolean isSimulationRunnig = false;
/**
* Singleton constructor
*/
private LightEditor() {
super();
}
/**
* Used for invoking instance
*
* @return
*/
public static LightEditor getInstance() {
return lightEditor;
}
/**
* Initialises an instance of Main GUI
*/
public void init() {
// Set size
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(new TitledBorder("Traffic Lights"));
setPreferredSize(new Dimension(AppConstants.APP_LEFT_COLUMN_WIDGET_WIDTH, AppConstants.APP_LEFT_COLUMN_WIDGET_HEIGHT));
content.setSize(500, 400);
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
JPanel topButtonPanel = new JPanel();
topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.X_AXIS));
JButton generateLightsButton = new JButton("Generate traffic lights");
topButtonPanel.add(generateLightsButton);
content.add(topButtonPanel);
generateLightsButton.addActionListener(lightGenerateListener);
JPanel firstPanel = new JPanel();
firstPanel.setLayout(new BoxLayout(firstPanel, BoxLayout.Y_AXIS));
content.add(firstPanel);
JPanel tlPanel = new JPanel();
tlPanel.setLayout(new BoxLayout(tlPanel, BoxLayout.Y_AXIS));
tlPanel.add(new JLabel("Traffic lights"));
JScrollPane tlScrollPanel = new JScrollPane(tlList);
tlScrollPanel.setMaximumSize(new Dimension(300, 100));
tlPanel.add(tlScrollPanel);
JPanel tlBottomPanel = new JPanel();
tlBottomPanel.setLayout(new BoxLayout(tlBottomPanel, BoxLayout.X_AXIS));
JPanel tlBottomRightPanel = new JPanel();
tlBottomRightPanel.setLayout(new BoxLayout(tlBottomRightPanel, BoxLayout.X_AXIS));
JButton editButton = new JButton("Edit");
editButton.addActionListener(editButtonListener);
JButton removeButton = new JButton("Remove");
removeButton.addActionListener(removeButtonListener);
tlBottomRightPanel.add(editButton);
tlBottomRightPanel.add(removeButton);
tlBottomPanel.add(tlBottomRightPanel);
tlPanel.add(tlBottomPanel);
content.add(tlPanel);
JPanel junctionPanel = new JPanel();
junctionPanel.setLayout(new BoxLayout(junctionPanel, BoxLayout.Y_AXIS));
junctionPanel.add(new JLabel("Junctions"));
JButton convertButton = new JButton("Convert to traffic light");
convertButton.addActionListener(convertButtonListener);
JScrollPane junctionScrollPanel = new JScrollPane(junctionList);
junctionScrollPanel.setMaximumSize(new Dimension(300, 100));
junctionPanel.add(junctionScrollPanel);
junctionPanel.add(convertButton);
junctionList.setVisibleRowCount(5);
content.add(junctionPanel);
tlModel.addElement("1");
// Set scroller
scrollPane = new JScrollPane(content);
scrollPane.setSize(AppConstants.APP_LEFT_COLUMN_WIDGET_WIDTH, AppConstants.APP_LEFT_COLUMN_WIDGET_HEIGHT);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
add(scrollPane);
setVisible(true);
//SimulationScreen.getInstance().traciConnector.conn.socket
}
private ActionListener lightGenerateListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ArrayList<Junction> idList = new TrafficLightReader().readNetworkFile(networkFile);
List<String> randomIds = getRandomJunctions(idList);
trafficLightIDs = randomIds;
createTrafficLights(randomIds);
if (randomIds.isEmpty()) {
JOptionPane.showMessageDialog(null, "Could not find any junctions that could be converted into traffic lights");
} else {
//JOptionPane.showMessageDialog(null, "Created " + randomIds.size() + " traffic lights");
}
}
};
public void generateRandomly() {
ArrayList<Junction> idList = new TrafficLightReader().readNetworkFile(networkFile);
List<String> randomIds = getRandomJunctions(idList);
trafficLightIDs = randomIds;
createTrafficLights(randomIds);
readNetworkFile();
}
public void triggerGeneration() {
readNetworkFile();
}
public void resetLights() {
//trafficLightIDs = null;
tlModel = new DefaultListModel();
junctionModel = new DefaultListModel();
CreateMapFrame.getInstance().createMap();
}
public void convertToTrafficLight(String id) {
/*if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null, "Do you want to add traffic light to this junction?")) {
if (isSimulationRunnig) {
JOptionPane.showMessageDialog(null, "Please note that the changes will not be reflected during this simulation");
}
System.out.println("Converting junction " + id + " to traffic light");
createTrafficLights(Arrays.asList(id));
// Refresh data from the network file
readNetworkFile();
}*/
createTrafficLights(Arrays.asList(id));
// Refresh data from the network file
readNetworkFile();
}
public void removeTrafficLight(String id) {
removeTrafficLights(Arrays.asList(id));
JOptionPane.showMessageDialog(null, "Traffic light with ID " + id + " has been removed");
readNetworkFile();
}
private void clearLists() {
tlModel.clear();
junctionModel.clear();
CreateSimulationFrame.getInstance().jListTrafficLights.removeAll();
CreateSimulationFrame.getInstance().jListJunctions.removeAll();
System.out.println("Tlight" + tlModel);
System.out.println("Junc" + junctionModel);
System.out.println("---");
}
private ActionListener convertButtonListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null, "Do you want to transform this junction to a traffic light?")) {
//System.out.println("Converting junction " + junction.getId() + " to traffic light");
//createTrafficLights(Arrays.asList(junction.getId()));
// Refresh data from the network file
readNetworkFile();
}
}
};
public void showReport() {
//TODO: Implement
}
private ActionListener editButtonListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String id = (String) tlList.getSelectedValue();
try {
new TrafficLighStateWindow(id);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
//new LightModifier(junction.getId()).changeLight();
}
};
private ActionListener removeButtonListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
int index = tlList.getSelectedIndex();
if (index == -1) {
JOptionPane.showMessageDialog(null, "Please select a traffic light to remove");
return;
}
if (isSimulationRunnig) {
//removeTrafficLights();
}
}
};
public void showTLOnSummoGUI(String id) throws UnknownHostException, IOException {
/*if (isSimulationRunnig) {
Socket socket = new Socket("localhost", 3445);
new ReadTrafficLightState(socket).goToTrafficLight(id);
}*/
}
/*
* Populates the junction and traffic light tables from the network file.
*/
public void readNetworkFile() {
if (networkFile == null || "".equals(networkFile)) {
System.out.println("Network file is empy, cannot refresh junction and traffic light list");
} else {
System.out.println("Reading network file " + networkFile + ", refreshing junction and traffic light list");
clearLists();
ArrayList<Junction> tlList = new TrafficLightReader().readTLogic(networkFile);
for (final Junction junction : tlList) {
String t = junction.getType();
/*if (junction.getType().equals("traffic_light")) {
tlModel.addElement(junction.getId());
} else {
junctionModel.addElement(junction.getId());
}*/
tlModel.addElement(junction.getId());
}
ArrayList<Junction> idList = new TrafficLightReader().readNetworkFile(networkFile);
for (final Junction junction1 : idList) {
String t = junction1.getType();
String id = junction1.getId();
/*if (junction.getType().equals("traffic_light")) {
tlModel.addElement(junction.getId());
} else {
junctionModel.addElement(junction.getId());
}*/
if (findJunction(id)) {
junctionModel.addElement(junction1.getId());
}
}
System.out.println("Read traffic:" + tlModel);
System.out.println("Read junction:" + junctionModel);
}
}
private boolean findJunction(String id) {
boolean result = true;
for (int i = 0; i < tlModel.size(); i++) {
String t = String.valueOf(tlModel.get(i));
if (t.equals(id)) {
result = false;
break;
}
}
return result;
}
/*
* This method receives a list of junctions, filters out all the traffic
* lights and returns a random subset of junction IDs. This will be used
* to allow the user to generate random traffic lights for any network.
*
* @param junctions represents the list of junctions in the network
*
* @returns random list of junction IDs with the traffic lights filtered out
*/
private List<String> getRandomJunctions(List<Junction> junctions) {
List<String> ids = new ArrayList<String>();
List<Junction> filteredJunctions = new ArrayList<Junction>();
for (Junction junction : junctions) {
/*if (!"traffic_light".equals(junction.getType())) {
}*/
filteredJunctions.add(junction);
}
// Check if we have any proper candidates
if (filteredJunctions.isEmpty()) {
return ids;
}
// Pick a random number representing the number of junctions that will be
// converted into traffic lights. There will be at least one, at most every
// one.
int pickCount = new Random().nextInt(filteredJunctions.size() - 1) + 1;
Collections.shuffle(filteredJunctions);
for (int i = 0; i < pickCount; i++) {
Junction selectedJunction = filteredJunctions.get(i);
ids.add(selectedJunction.getId());
}
return ids;
}
/*
* This method calls netconverter to convert a list of junctions into traffic lights.
*
* @param sumoPath is the path to the SUMO executables
* @param ids is the list of junctions that we want to convert into traffic lights
*/
private void createTrafficLights(List<String> ids) {
// If there are no junction IDs specified
if (ids.isEmpty()) {
System.out.println("Junction list empty, not trying to create traffic lights.");
return;
}
String commaSeparatedList = listToCSV(ids);
new Connector(ConnectorType.CONNECTOR_NETCONVERT).runCommand("-s " + networkFile + " --tls.set " + commaSeparatedList + " --output-file=" + networkFile);
}
/*
* Give a list of strings, create a single string with the list
* values separated by commas. Used by netconvert
*/
private String listToCSV(List<String> list) {
String commaSeparatedList = "";
for (int i = 0; i < list.size(); i++) {
commaSeparatedList = commaSeparatedList + list.get(i);
if (i < list.size() - 1) {
commaSeparatedList = commaSeparatedList + ",";
}
}
return commaSeparatedList;
}
/*
* Remove the selected traffic lights from the network file
* by using netconvert
*/
private void removeTrafficLights(List<String> ids) {
String commaSeparatedList = listToCSV(ids);
new Connector(ConnectorType.CONNECTOR_NETCONVERT).runCommand("-s " + networkFile + " --tls.unset " + commaSeparatedList + " --output-file=" + networkFile);
}
class TLListListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
System.out.println("list item: number " + tlList.getSelectedValue());
}
}
}