/*
 * 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;

import org.aglais.zms.AglaisZMS;
import org.aglais.zms.ui.tab.*;
import org.aglais.zms.util.VersionUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.ResourceBundle;

/**
 * Main application window that contains all UI tabs and components
 */
public class MainFrame {
    private static final String LOG_TAG = MainFrame.class.getSimpleName();

    private JPanel contentPane;
    private JTabbedPane mainTabbedPane;

    private final AglaisZMS zms;
    private Tab[] tabs;
    private JFrame frame;
    private boolean exitOnClose = true;

    /**
     * Creates a new {@link MainFrame} instance
     *
     * @param zms The {@link AglaisZMS} application instance
     */
    public MainFrame(AglaisZMS zms) {
        this.zms = zms;

        tabs = new Tab[]{
                new DashboardTab(zms),
                new SpeciesTab(zms),
                new SettingsTab(zms),
                new AboutTab(zms)
        };
        if (VersionUtil.isDevBuild(VersionUtil.getVersion())) {
            tabs = Arrays.copyOf(tabs, tabs.length + 1);
            tabs[tabs.length - 1] = new DebugInfoTab(zms);
        }
    }

    /**
     * Get the backing {@link JFrame}
     *
     * @return The frame
     */
    public JFrame getFrame() {
        return frame;
    }

    /**
     * Set if System.exit(0) should be called when the frame is closing
     *
     * @param exitOnClose True if System.exit(0) should be called on close
     */
    public void setExitOnClose(boolean exitOnClose) {
        this.exitOnClose = exitOnClose;
    }

    /**
     * Initializes and displays the main application window
     * - Creates and configures the JFrame
     * - Adds the application tabs
     * - Makes the window visible
     */
    public void start() {
        ResourceBundle uiBundle = ResourceBundle.getBundle("ui");
        String programName = uiBundle.getString("program_name");
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        frame = new JFrame(programName);
        frame.setIconImages(zms.getIconImages());
        frame.setContentPane(contentPane);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.pack();
        frame.setMinimumSize(new Dimension(100, 100));
        frame.setSize((int) (screenSize.getWidth() / 2), (int) (screenSize.getHeight() / 2));
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);

        // Custom close listener to check for unsaved changes
        frame.addWindowListener(new java.awt.event.WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Tab tab = tabs[mainTabbedPane.getSelectedIndex()];

                if (!tab.ensureNoUnsavedChanges())
                    return;

                tab.hide();

                frame.dispose();
                if (exitOnClose)
                    System.exit(0);
            }
        });
        // Ctrl+S support
        frame.getRootPane().registerKeyboardAction((e) -> {
            Tab tab = tabs[mainTabbedPane.getSelectedIndex()];

            tab.saveChangesWithUI();
        }, KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);

        // Add Tabs
        Tab.registerAll(mainTabbedPane, uiBundle, tabs);

        frame.setVisible(true);
    }
}
