package name.admitriev.jhelper.ui;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;
import name.admitriev.jhelper.components.Configurator;
import name.admitriev.jhelper.parsing.Receiver;
import name.admitriev.jhelper.task.TaskData;
import net.egork.chelper.parser.Description;
import net.egork.chelper.parser.Parser;
import net.egork.chelper.parser.ParserTask;
import net.egork.chelper.task.Task;
import net.egork.chelper.task.TestType;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.VerticalLayout;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ParseDialog extends DialogWrapper {
private JComponent component;
private ComboBox<Parser> parserComboBox;
private ComboBox<TestType> testType;
private JBList<Description> contestList;
private Receiver contestReceiver = new Receiver.Empty();
private ParseListModel<Description> contestModel = new ParseListModel<>();
private JBList<Description> problemList;
private Receiver problemReceiver = new Receiver.Empty();
private ParseListModel<Description> problemModel = new ParseListModel<>();
private Project project;
public ParseDialog(@Nullable Project project) {
super(project);
this.project = project;
setTitle("Parse contest");
JPanel panel = new JPanel(new VerticalLayout());
parserComboBox = new ComboBox<>(Parser.PARSERS);
parserComboBox.setRenderer(
new ListCellRendererWrapper<Parser>() {
@Override
public void customize(JList list, Parser parser, int index, boolean selected, boolean hasFocus) {
setText(parser.getName());
setIcon(parser.getIcon());
}
}
);
parserComboBox.addActionListener(
e -> refresh()
);
testType = new ComboBox<>(TestType.values());
contestList = new JBList<>(contestModel);
contestList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
contestList.addListSelectionListener(
e -> {
problemReceiver.stop();
problemModel.removeAll();
Parser parser = (Parser) parserComboBox.getSelectedItem();
Description contest = contestList.getSelectedValue();
problemReceiver = generateProblemReceiver();
if (contest != null) {
new ParserTask(
contest.id, problemReceiver, parser
);
}
}
);
problemList = new JBList<>(problemModel);
problemList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JPanel contestsTasksPanel = new JPanel(new HorizontalLayout());
contestsTasksPanel.add(
new JBScrollPane(
contestList,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
)
);
contestsTasksPanel.add(
new JBScrollPane(
problemList,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
)
);
panel.add(LabeledComponent.create(parserComboBox, "Parser"));
panel.add(contestsTasksPanel);
panel.add(LabeledComponent.create(testType, "Test type"));
component = panel;
init();
}
private void refresh() {
Parser parser = (Parser) parserComboBox.getSelectedItem();
Description chosenDescription = contestList.getSelectedValue();
contestReceiver.stop();
contestModel.removeAll();
contestReceiver = generateContestReceiver(chosenDescription);
new ParserTask(
null, contestReceiver, parser
);
}
private Receiver generateProblemReceiver() {
return new Receiver() {
@Override
public void receiveDescriptions(Collection<Description> descriptions) {
Receiver thisReceiver = this;
SwingUtilities.invokeLater(
() -> {
//noinspection ObjectEquality
if (problemReceiver != thisReceiver) {
return;
}
boolean shouldMark = problemModel.getSize() == 0;
problemModel.addAll(descriptions);
if (shouldMark) {
problemList.setSelectionInterval(0, problemModel.getSize() - 1);
}
}
);
}
};
}
private Receiver generateContestReceiver(Description chosenDescription) {
return new Receiver() {
@Override
public void receiveDescriptions(Collection<Description> descriptions) {
Receiver thisReceiver = this;
SwingUtilities.invokeLater(
() -> {
//noinspection ObjectEquality
if (contestReceiver != thisReceiver) {
return;
}
boolean shouldMark = contestModel.getSize() == 0;
contestModel.addAll(descriptions);
if (shouldMark) {
for (Description contest : descriptions) {
if (chosenDescription != null && chosenDescription.id.equals(contest.id)) {
contestList.setSelectedValue(contest, true);
return;
}
}
if (contestModel.getSize() > 0) {
contestList.setSelectedIndex(0);
}
}
}
);
}
};
}
@Nullable
@Override
protected JComponent createCenterPanel() {
refresh();
return component;
}
public Collection<TaskData> getResult() {
List<TaskData> list = new ArrayList<>();
List<Description> selectedTasks = problemList.getSelectedValuesList();
Parser parser = (Parser) parserComboBox.getSelectedItem();
Configurator configurator = project.getComponent(Configurator.class);
Configurator.State configuration = configurator.getState();
String path = configuration.getTasksDirectory();
for (Object taskDescription : selectedTasks) {
Description description = (Description) taskDescription;
Task rawTask = parser.parseTask(description);
if (rawTask == null) {
Notificator.showNotification(
"Unable to parse task " + description.description,
"Connection problems or format change",
NotificationType.ERROR
);
continue;
}
TaskData myTask = new TaskData(
rawTask.name,
rawTask.taskClass,
String.format("%s/%s.cpp", path, rawTask.taskClass),
rawTask.input,
rawTask.output,
(TestType) testType.getSelectedItem(),
rawTask.tests
);
list.add(myTask);
}
return list;
}
}