// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.core.script.k1.configuration;

import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.panels.VerticalLayout;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle;
import org.jetbrains.kotlin.idea.core.script.k1.ScriptDefinitionsManager;
import org.jetbrains.kotlin.idea.core.script.k1.settings.KotlinScriptingSettingsImpl;
import org.jetbrains.kotlin.idea.core.script.shared.KotlinScriptingSetttingsIdKt;
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition;
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider;

import javax.swing.*;

import static kotlin.streams.jdk8.StreamsKt.asStream;


public class KotlinScriptingSettingsConfigurable implements SearchableConfigurable {

    private JPanel root;
    private JPanel panelScriptDefinitionsChooser;
    private JPanel additionalSettingsPanel;

    private final KotlinScriptDefinitionsModel model;
    private final ScriptDefinitionsManager manager;
    private final KotlinScriptingSettingsImpl settings;

    public KotlinScriptingSettingsConfigurable(Project project) {
        manager = ScriptDefinitionsManager.Companion.getInstance(project);
        settings = KotlinScriptingSettingsImpl.Companion.getInstance(project);
        model = KotlinScriptDefinitionsModel.Companion.createModel(
                asStream(ScriptDefinitionProvider.Companion.getInstance(project).getCurrentDefinitions()).toList(), settings);
    }

    @Override
    public @Nullable JComponent createComponent() {
        panelScriptDefinitionsChooser.setLayout(new VerticalLayout(0));

        panelScriptDefinitionsChooser.add(new TitledSeparator(KotlinBundle.message("kotlin.script.definitions.title")));

        JLabel commentLabel = new JLabel(KotlinBundle.message("kotlin.script.definitions.model.name.autoReloadScriptDependencies.description"));
        commentLabel.setForeground(UIUtil.getContextHelpForeground());
        panelScriptDefinitionsChooser.add(commentLabel);

        TableView<ModelDescriptor> table = new TableView<>(model);
        panelScriptDefinitionsChooser.add(
                ToolbarDecorator.createDecorator(table)
                        .disableAddAction()
                        .disableRemoveAction()
                        .createPanel()
        );
        table.setVisibleRowCount(12);

        additionalSettingsPanel.setLayout(new VerticalLayout(0));
        return root;
    }

    @Override
    public boolean isModified() {
        return isScriptDefinitionsChanged();
    }

    @Override
    public void apply() throws ConfigurationException {
        if (isScriptDefinitionsChanged()) {
            for (ModelDescriptor item : model.getItems()) {
                ScriptDefinition definition = item.getDefinition();
                int order = model.getItems().indexOf(item);
                settings.setOrder(definition, order);
                settings.setEnabled(definition, item.isEnabled());
                settings.setAutoReloadConfigurations(definition, item.getAutoReloadConfigurations());
            }

            manager.reorderDefinitions();
        }
    }

    @Override
    public void reset() {
        model.setDefinitions(asStream(manager.getCurrentDefinitions()).toList(), settings);
    }

    private boolean isScriptDefinitionsChanged() {
        for (ModelDescriptor item : model.getItems()) {
            if (settings.isScriptDefinitionEnabled(item.getDefinition()) != item.isEnabled()) {
                return true;
            }
            if (settings.autoReloadConfigurations(item.getDefinition()) != item.getAutoReloadConfigurations()) {
                return true;
            }
        }
        return !model.getDefinitions().equals(asStream(manager.getCurrentDefinitions()).toList());
    }


    @Override
    @Nls
    public String getDisplayName() {
        return KotlinBundle.message("script.name.kotlin.scripting");
    }

    @Override
    public @NotNull String getId() {
        return KotlinScriptingSetttingsIdKt.KOTLIN_SCRIPTING_SETTINGS_ID;
    }
}
