/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2021 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.installer.screens;

import org.apache.commons.lang3.StringUtils;
import org.jboss.installer.common.FileChooserPanel;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.MavenRepositoryLoader;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.validators.MavenOfflineRepositoryValidator;
import org.jboss.installer.validators.WritableFolderValidator;

import javax.swing.Box;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static javax.swing.JFileChooser.DIRECTORIES_ONLY;
import static javax.swing.JFileChooser.FILES_AND_DIRECTORIES;
import static org.jboss.installer.Installer.EAP_VERSION;
import static org.jboss.installer.validators.WritableFolderValidator.EMPTY_DIRECTORY_DISABLED;

public class TargetScreen extends DefaultScreen {

    public static final String NAME = "TargetScreen";

    private static final String DESC_KEY="target_screen.desc";
    private static final String TITLE_KEY="target_screen.title";
    private static final String OVERRIDE_MAVEN_REPOSITORY_DEFAULT_KEY = "target_screen.override.maven.repository.desc";

    private static final String MAVEN_REPOSITORY_DEFAULT_KEY = "target_screen.maven.repository.desc";

    private final FileChooserPanel fileChooser = FileChooserPanel.builder(langUtils, DIRECTORIES_ONLY, mnemonicUtils)
            .baseFolder(Paths.get(HOME_DIR, "EAP-" + EAP_VERSION).toString()).build();

    private final WritableFolderValidator installationTargetValidator;

    private final JCheckBox repositoryCheckBox = createCheckBox(OVERRIDE_MAVEN_REPOSITORY_DEFAULT_KEY, true, false);

    private FileChooserPanel repositoryChooser;

    private final MavenOfflineRepositoryValidator mavenOfflineRepositoryPathValidator;
    private String defaultRepositories = "";

    public TargetScreen(LanguageUtils langUtils) {
        super(langUtils);
        this.installationTargetValidator = new WritableFolderValidator("target_screen", langUtils);
        this.mavenOfflineRepositoryPathValidator = new MavenOfflineRepositoryValidator(langUtils);
    }

    @Override
    public void load(InstallationData installationData) {
        repositoryCheckBox.requestFocus();
        defaultRepositories = getDefaultRepositories(installationData);
    }

    private static String getDefaultRepositories(InstallationData installationData) {
        final Map<String, URL> map;
        if (installationData.getMavenRepositories().isEmpty()) {
            map = installationData.getDefaultMavenRepositories();
        } else {
            map = installationData.getMavenRepositories();
        }
        return StringUtils.join(map.values(), ",");
    }

    @Override
    public String getTitle() {
        return langUtils.getString(TITLE_KEY);
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public JPanel getContent() {

        if (repositoryChooser == null) {
            repositoryChooser = FileChooserPanel.builder(langUtils, FILES_AND_DIRECTORIES, mnemonicUtils)
                    .fileFilter(new FileNameExtensionFilter("ZIP files", "zip")).build();
            repositoryChooser.setEnabled(false);
            // set the default value first time screen is loaded to preserve user changes on next/prev pages
            // the repositoryChooser cannot be initiated in constructor because we need installationData provided by load()
            repositoryChooser.setPath(defaultRepositories);
        }

        JPanel content = new JPanel(new GridBagLayout());
        GridBagConstraints c = initializeConstraints();
        c.insets = FIELD_ROW_INSET;
        c.gridwidth = 1;
        content.add(fileChooser, c);

        content.add(createFieldLabel(DESC_KEY), c);
        c.gridy++;

        content.add(fileChooser, c);
        c.gridy++;

        repositoryCheckBox.addItemListener(itemEvent -> {
            if (repositoryCheckBox.isSelected()) {
                repositoryChooser.setEnabled(true);
            } else {
                repositoryChooser.setEnabled(false);
            }
        });
        content.add(repositoryCheckBox, c);
        c.gridy++;

        content.add(createFieldLabel(MAVEN_REPOSITORY_DEFAULT_KEY), c);
        c.gridy++;
        content.add(repositoryChooser, c);

        // placeholder to fill available vertical space
        c.gridy++;
        c.weighty = 1;
        content.add(Box.createVerticalBox(), c);

        return content;
    }

    @Override
    public JComponent getDefaultFocusComponent() {
        return fileChooser;
    }

    @Override
    public ValidationResult validate() {
        ValidationResult validationResult = installationTargetValidator.validate(fileChooser.getText(), EMPTY_DIRECTORY_DISABLED);
        if (validationResult.getResult().equals(ValidationResult.Result.OK) && repositoryCheckBox.isSelected()) {
            validationResult = mavenOfflineRepositoryPathValidator.validate(repositoryChooser.getText());
        }
        return validationResult;
    }

    @Override
    public void record(InstallationData installationData) {
        final Path installPath = fileChooser.getText()==null?null:Paths.get(fileChooser.getText());
        installationData.setTargetFolder(installPath);

        Map<String, URL> repositories;
        if (repositoryCheckBox.isSelected() && repositoryChooser.getText() != null) {
            // it is either a comma separated list of maven source repositories (URLs)
            // , or it is an offline maven repository directory or an offline maven repository ZIP file
            final List<String> offlineRepositories = Arrays.asList(repositoryChooser.getText().split(","));
            repositories = MavenRepositoryLoader.parseToUrls(offlineRepositories);
        } else {
            repositories = installationData.getDefaultMavenRepositories();
        }

        installationData.setMavenRepositories(repositories);
    }
}
