package app.views.match.components; import app.data.entity.Game; import app.data.entity.Match; import app.data.entity.Match.State; import app.data.service.ChessComService; import app.data.service.MatchService; import app.gameimage.GameImageService; import app.navigation.match.MatchNavigation; import app.utils.ChessComUtils; import app.utils.ComponentUtils; import app.utils.MatchUtils; import app.utils.TimeControl; import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.UI; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.shared.Registration; import java.util.*; import static app.data.entity.Match.State.*; import static app.utils.TimeControl.*; import static com.vaadin.flow.component.button.ButtonVariant.LUMO_PRIMARY; public class EditMatchCard extends VerticalLayout { private final MatchNavigation matchNavigation; private final MatchService matchService; private final ChessComService chessComService; private final GameImageService gameImageService; private final VerticalLayout formLayout = new VerticalLayout(); private final List tenMinuteTextFields = new ArrayList<>(); private final List fiveMinuteTextFields = new ArrayList<>(); private final List threeMinuteTextFields = new ArrayList<>(); private final Button submitButton = new Button("Submit", new Icon(VaadinIcon.CHECK)); // TODO: disable when no 6 values in form, and make sure you don't freeze forever when there are wrong entries // TODO: use overlapping progress here private Registration editSubmitButtonRegistration; private final Button editCancelButton = new Button("Cancel", new Icon(VaadinIcon.CLOSE)); private Registration editCancelButtonRegistration; private final Button chessComButton = new Button("Autofill with the latest games between the players", new Icon(VaadinIcon.MAGIC)); private Registration chessComButtonButtonRegistration; HorizontalLayout adminButtonLayout = new HorizontalLayout(); private Registration sixZeroButtonRegistration; private final Button sixZeroButton = new Button("6 - 0", new Icon(VaadinIcon.CHECK)); private Registration zeroSixButtonRegistration; private final Button zeroSixButton = new Button("0 - 6", new Icon(VaadinIcon.CHECK)); private Registration zeroZeroButtonRegistration; private final Button zeroZeroButton = new Button("0 - 0", new Icon(VaadinIcon.CHECK)); private Match match; public EditMatchCard(MatchNavigation matchNavigation, ChessComService chessComService, GameImageService gameImageService) { this.matchNavigation = matchNavigation; this.chessComService = chessComService; this.matchService = matchNavigation.getMatchService(); this.gameImageService = gameImageService; defineLayout(); } //////////// // LAYOUT // //////////// private void defineLayout() { setAlignItems(Alignment.CENTER); setWidth(""); addClassName("card"); add(chessComButton); defineTextFields(); defineSubmitButton(); addSubmitAndCancelButtons(); addAdminButtons(); } private void defineTextFields() { add(formLayout); formLayout.setPadding(false); defineTextFields(tenMinuteTextFields, TEN_MINUTES, 1); defineTextFields(fiveMinuteTextFields, FIVE_MINUTES, 3); defineTextFields(threeMinuteTextFields, THREE_MINUTES, 5); } private void defineTextFields(List list, TimeControl timeControl, int startGameNumber) { for (int i = 0; i < 2; i++) { TextField textField = new TextField(); textField.setWidth("23em"); textField.setPlaceholder("Please enter URL"); String gameString = String.format("Game %d", startGameNumber + i); String timeControlString = timeControl.toPresentationString(); HorizontalLayout labelLayout = ComponentUtils.getFormattedLabelWithParentheses(gameString, timeControlString); labelLayout.setSpacing(false); labelLayout.setAlignItems(Alignment.CENTER); labelLayout.setJustifyContentMode(JustifyContentMode.START); HorizontalLayout row = new HorizontalLayout(labelLayout, textField); row.setWidthFull(); row.setJustifyContentMode(JustifyContentMode.BETWEEN); formLayout.add(row); list.add(textField); } } private void defineSubmitButton() { submitButton.addThemeVariants(LUMO_PRIMARY); } private void addSubmitAndCancelButtons() { HorizontalLayout buttonLayout = new HorizontalLayout(); buttonLayout.setAlignItems(Alignment.CENTER); buttonLayout.setJustifyContentMode(JustifyContentMode.CENTER); buttonLayout.add(submitButton, editCancelButton); add(buttonLayout); } private void addAdminButtons() { sixZeroButton.addThemeVariants(LUMO_PRIMARY); zeroSixButton.addThemeVariants(LUMO_PRIMARY); zeroZeroButton.addThemeVariants(LUMO_PRIMARY); adminButtonLayout.setAlignItems(Alignment.CENTER); adminButtonLayout.setJustifyContentMode(JustifyContentMode.CENTER); adminButtonLayout.add(sixZeroButton, zeroSixButton, zeroZeroButton); } ///////////// // CONTENT // ///////////// void configureContent(Match match) { this.match = match; clearTextFields(); fillTextFieldsWithURLs(MatchUtils.getGamesMap(match)); configureChessComButton(); configureEditSubmitButton(); configureEditCancelButton(); configureAdminButtons(); } private void clearTextFields() { for (List list : Set.of(tenMinuteTextFields, fiveMinuteTextFields, threeMinuteTextFields)) { list.forEach(textField -> textField.setValue("")); } } private void fillTextFieldsWithURLs(Map> games) { for (int i = 0; i < 2; i++) { if (games.get(TEN_MINUTES).size() > i) tenMinuteTextFields.get(i).setValue(ChessComUtils.getGameURL(games.get(TEN_MINUTES).get(i))); if (games.get(FIVE_MINUTES).size() > i) fiveMinuteTextFields.get(i).setValue(ChessComUtils.getGameURL(games.get(FIVE_MINUTES).get(i))); if (games.get(THREE_MINUTES).size() > i) threeMinuteTextFields.get(i).setValue(ChessComUtils.getGameURL(games.get(THREE_MINUTES).get(i))); } } private void configureChessComButton() { if (chessComButtonButtonRegistration != null) chessComButtonButtonRegistration.remove(); chessComButtonButtonRegistration = chessComButton.addClickListener(createChessComButtonClickListener()); } private ComponentEventListener> createChessComButtonClickListener() { return event -> { Map> gamesBetweenPlayers = chessComService.getLatestGamesBetweenPlayers(match, 2); fillTextFieldsWithURLs(gamesBetweenPlayers); }; } private void configureEditSubmitButton() { if (editSubmitButtonRegistration != null) editSubmitButtonRegistration.remove(); editSubmitButtonRegistration = submitButton.addClickListener(createEditSubmitButtonClickListener()); } private ComponentEventListener> createEditSubmitButtonClickListener() { return event -> { match.getGames().clear(); addGamesToMatchFromFieldValues(); matchService.update(match); match.getGames().forEach(gameImageService::createImageIfNotPresent); matchNavigation.setEditFlag(false); }; } private void addGamesToMatchFromFieldValues() { for (TextField textField : getAllTextfields()) { Optional game = chessComService.getGame(textField.getValue().replace("/live/game/", "/game/live/"), match); // TODO: handle this when Optional is empty! game.ifPresent(value -> match.getGames().add(value)); } if (match.getGames().size() > 0) { match.setState(PLAYED); } } private List getAllTextfields() { List list = new ArrayList<>(); list.addAll(tenMinuteTextFields); list.addAll(fiveMinuteTextFields); list.addAll(threeMinuteTextFields); return list; } private void configureEditCancelButton() { if (editCancelButtonRegistration != null) editCancelButtonRegistration.remove(); editCancelButtonRegistration = editCancelButton.addClickListener(createEditCancelButtonListener()); } private void configureAdminButtons() { if (matchNavigation.adminFlag()) { configureSixZeroButton(); configureZeroSixButton(); configureZeroZeroButton(); add(adminButtonLayout); } else { remove(adminButtonLayout); } } private void configureSixZeroButton() { if (sixZeroButtonRegistration != null) sixZeroButtonRegistration.remove(); sixZeroButtonRegistration = sixZeroButton.addClickListener(event -> submitAdminDecision(SIX_ZERO)); } private void configureZeroSixButton() { if (zeroSixButtonRegistration != null) zeroSixButtonRegistration.remove(); zeroSixButtonRegistration = zeroSixButton.addClickListener(event -> submitAdminDecision(ZERO_SIX)); } private void configureZeroZeroButton() { if (zeroZeroButtonRegistration != null) zeroZeroButtonRegistration.remove(); zeroZeroButtonRegistration = zeroZeroButton.addClickListener(event -> submitAdminDecision(ZERO_ZERO)); } private void submitAdminDecision(State sixZero) { match.getGames().clear(); match.setState(sixZero); matchService.update(match); matchNavigation.setEditFlag(false); matchNavigation.setAdminFlag(false); } private ComponentEventListener> createEditCancelButtonListener() { return event -> UI.getCurrent().navigate(String.format("matchday/%s", matchNavigation.getWildcardParam().replace("edit/", ""))); } }