/*
 * Copyright (C) 2025-2026  Tim Zimmermann <tim@aglais.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.aglais.zms.ui.tab;

import org.aglais.zms.AglaisZMS;
import org.aglais.zms.db.core.model.Species;
import org.aglais.zms.ui.tab.species.SpeciesAncestryTab;
import org.aglais.zms.ui.tab.species.SpeciesInfoTab;
import org.aglais.zms.ui.tab.species.SpeciesOriginTab;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;

import static com.formdev.flatlaf.FlatClientProperties.*;
import static javax.swing.SwingConstants.LEFT;

/**
 * Tab for managing species.
 * Provides functionality to view, add and edit species information.
 */
public class SpeciesTab extends Tab implements ISubTabbedTab {
    private JPanel contentPane;
    private JPanel speciesList;
    private JTabbedPane speciesTabbedPane;
    private JButton addSpeciesButton;
    private JScrollPane speciesScrollPane;

    private final List<JToggleButton> buttons = new ArrayList<>();
    private Species selectedSpecies;
    private final SubTab<?>[] tabs;

    /**
     * Creates a new SpeciesTab with the given {@link AglaisZMS} instance
     *
     * @param zms The {@link AglaisZMS} instance this tab belongs to
     */
    public SpeciesTab(AglaisZMS zms) {
        super(zms);

        tabs = new SubTab[] {
                new SpeciesInfoTab(zms, this),
                new SpeciesAncestryTab(zms, this),
                new SpeciesOriginTab(zms, this)
        };

        // Hide scrollbar border for tab-style toggle buttons looking like native tabs
        speciesScrollPane.setBorder(BorderFactory.createEmptyBorder());
        speciesList.setLayout(new BoxLayout(speciesList, BoxLayout.Y_AXIS));
        addSpeciesButton.addActionListener((event) -> {
            if (!ensureNoUnsavedChanges())
                return;

            ResourceBundle uiBundle = ResourceBundle.getBundle("ui");

            Species species = new Species(-1, "", "", "", "", null);
            species = zms.getClient().addSpecies(species);

            if (species == null) {
                JOptionPane.showMessageDialog(contentPane, uiBundle.getString("error_add_species_failed"),
                        uiBundle.getString("error"), JOptionPane.ERROR_MESSAGE);
                return;
            }

            if (ensureNoUnsavedChanges()) {
                selectedSpecies = species;

                // Add to list
                show();

                // Ensure info tab is updated
                for (JToggleButton button : buttons) {
                    if (button.isSelected()) {
                        button.doClick();
                        break;
                    }
                }
            }
        });
    }

    /**
     * Gets the currently selected species
     *
     * @return The selected Species object, or null if none selected
     */
    public Species getSelectedSpecies() {
        return selectedSpecies;
    }

    @Override
    public void onShow() {
        int selectedButtonIndex = -1;
        for (int i = 0; i < buttons.size(); i++) {
            if (buttons.get(i).isSelected()) {
                selectedButtonIndex = i;
                break;
            }
        }

        speciesList.removeAll();
        buttons.clear();

        List<Species> allSpecies = zms.getClient().getAllSpecies();
        allSpecies.sort(Comparator.comparing(Species::getScientificName));

        for (Species species : allSpecies) {
            StringBuilder sb = new StringBuilder("<html>" + species.getScientificName());
            if (species.getOrigin() != null && !species.getOrigin().isEmpty()) {
                sb.append("<br/>");
                sb.append(species.getOrigin());
            }
            sb.append("</html>");

            JToggleButton button = new JToggleButton(sb.toString());
            button.setHorizontalAlignment(LEFT);
            button.putClientProperty(BUTTON_TYPE, BUTTON_TYPE_TAB);
            button.putClientProperty(TAB_BUTTON_UNDERLINE_PLACEMENT, LEFT);
            buttons.add(button);
            speciesList.add(button);
            speciesList.add(new JSeparator());

            if (selectedSpecies != null && selectedSpecies.equals(species)) {
                selectedSpecies = species;
                button.setSelected(true);
                SwingUtilities.invokeLater(() -> speciesScrollPane.getViewport().scrollRectToVisible(button.getBounds()));
            }

            button.addActionListener((event) -> {
                if (selectedSpecies != null && !selectedSpecies.equals(species) && !ensureNoUnsavedChanges())
                    return;
                selectedSpecies = species;

                for (JToggleButton b : buttons) {
                    b.setSelected(false);
                }
                button.setSelected(true);

                registerSubTabs();
            });
        }

        if (selectedSpecies != null && !allSpecies.contains(selectedSpecies)) {
            selectedSpecies = null;

            selectedButtonIndex = Math.max(selectedButtonIndex - 1, 0);
            if (buttons.size() > selectedButtonIndex)
                buttons.get(selectedButtonIndex).doClick();
            else
                unregisterSubTabs();
        }
    }

    @Override
    public @NotNull JComponent getContentPane() {
        return contentPane;
    }

    @Override
    public JTabbedPane getTabbedPane() {
        return speciesTabbedPane;
    }

    @Override
    public SubTab<?>[] getTabs() {
        return tabs;
    }

    @Override
    public String getSaveTitle() {
        return selectedSpecies != null ? selectedSpecies.getScientificName() : null;
    }
}
