/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.netbeans.modules.gradle.newproject;

import java.awt.Component;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.spi.project.ui.support.CommonProjectActions;
import org.netbeans.spi.project.ui.support.ProjectChooser;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle.Messages;

import static org.netbeans.modules.gradle.spi.newproject.BaseGradleWizardIterator.*;

public final class ProjectAttributesPanelVisual extends JPanel implements DocumentListener {

    public static final String PROP_PROJECT_NAME = "projectName";         //NOI18N
    private static final String PROP_CHANGED_PKG = "changedPackageBase";  //NOI18N

    final ProjectAttriburesPanel panel;

    private boolean changedPackageBase = false;

    /**
     * Creates new form NewProjectVisualPanel1
     */
    @SuppressWarnings("LeakingThisInConstructor")
    public ProjectAttributesPanelVisual(ProjectAttriburesPanel panel, Component bottomComponent) {
        this.panel = panel;

        initComponents();
        if (bottomComponent != null) {
            pnlExtraSpace.add(bottomComponent);
        }
        tfProjectName.getDocument().addDocumentListener(this);
        tfProjectLocation.getDocument().addDocumentListener(this);
        tfGroup.getDocument().addDocumentListener(this);
        tfPackageBase.getDocument().addDocumentListener(this);
    }

    @Override
    @Messages("NameAndLocationPanel=Name and Location")
    public String getName() {
        return Bundle.NameAndLocationPanel();
    }

    public void setProjectName(String name) {
        tfProjectName.setText(name);
    }

    public String getProjectName() {
        return tfProjectName.getText();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lbProjectName = new javax.swing.JLabel();
        lbProjectLocation = new javax.swing.JLabel();
        lbProjectFolder = new javax.swing.JLabel();
        tfProjectName = new javax.swing.JTextField();
        tfProjectLocation = new javax.swing.JTextField();
        tfProjectFolder = new javax.swing.JTextField();
        btBrowse = new javax.swing.JButton();
        tfDescription = new javax.swing.JTextField();
        tfGroup = new javax.swing.JTextField();
        tfVersion = new javax.swing.JTextField();
        tfPackageBase = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        lbDescription = new javax.swing.JLabel();
        lbGroup = new javax.swing.JLabel();
        lbVersion = new javax.swing.JLabel();
        lbPackageBase = new javax.swing.JLabel();
        pnlExtraSpace = new javax.swing.JPanel();
        cbInitWrapper = new javax.swing.JCheckBox();

        lbProjectName.setLabelFor(lbProjectName);
        org.openide.awt.Mnemonics.setLocalizedText(lbProjectName, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbProjectName.text")); // NOI18N

        lbProjectLocation.setLabelFor(tfProjectLocation);
        org.openide.awt.Mnemonics.setLocalizedText(lbProjectLocation, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbProjectLocation.text")); // NOI18N

        lbProjectFolder.setLabelFor(tfProjectFolder);
        org.openide.awt.Mnemonics.setLocalizedText(lbProjectFolder, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbProjectFolder.text")); // NOI18N

        tfProjectFolder.setText(org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.tfProjectFolder.text")); // NOI18N
        tfProjectFolder.setEnabled(false);
        tfProjectFolder.setFocusable(false);

        org.openide.awt.Mnemonics.setLocalizedText(btBrowse, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.btBrowse.text")); // NOI18N
        btBrowse.setActionCommand("BROWSE"); // NOI18N
        btBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btBrowseActionPerformed(evt);
            }
        });

        tfVersion.setToolTipText(org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.tfVersion.toolTipText")); // NOI18N

        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "LBL_optional")); // NOI18N
        jLabel1.setEnabled(false);

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "LBL_optional")); // NOI18N
        jLabel2.setEnabled(false);

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "LBL_optional")); // NOI18N
        jLabel3.setEnabled(false);

        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "LBL_optional")); // NOI18N
        jLabel4.setEnabled(false);

        lbDescription.setLabelFor(tfDescription);
        org.openide.awt.Mnemonics.setLocalizedText(lbDescription, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbDescription.text")); // NOI18N

        lbGroup.setLabelFor(tfGroup);
        org.openide.awt.Mnemonics.setLocalizedText(lbGroup, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbGroup.text")); // NOI18N

        lbVersion.setLabelFor(tfVersion);
        org.openide.awt.Mnemonics.setLocalizedText(lbVersion, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbVersion.text")); // NOI18N

        lbPackageBase.setLabelFor(tfPackageBase);
        org.openide.awt.Mnemonics.setLocalizedText(lbPackageBase, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.lbPackageBase.text")); // NOI18N

        pnlExtraSpace.setLayout(new java.awt.BorderLayout());

        org.openide.awt.Mnemonics.setLocalizedText(cbInitWrapper, org.openide.util.NbBundle.getMessage(ProjectAttributesPanelVisual.class, "ProjectAttributesPanelVisual.cbInitWrapper.text")); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pnlExtraSpace, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(lbProjectLocation, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbProjectName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbPackageBase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbVersion, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbGroup, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbProjectFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(tfPackageBase, javax.swing.GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
                            .addComponent(tfGroup)
                            .addComponent(tfDescription)
                            .addComponent(tfProjectLocation)
                            .addComponent(tfProjectFolder)
                            .addComponent(tfVersion)
                            .addComponent(tfProjectName))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(btBrowse, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(cbInitWrapper)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(8, 8, 8)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lbProjectName)
                    .addComponent(tfProjectName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lbProjectLocation)
                    .addComponent(tfProjectLocation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btBrowse))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lbProjectFolder)
                    .addComponent(tfProjectFolder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tfDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(lbDescription))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tfGroup, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(lbGroup))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tfVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(lbVersion))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tfPackageBase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(lbPackageBase))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlExtraSpace, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cbInitWrapper)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    @Messages("TIT_Select_Project_Location=Select Project Location")
    private void btBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btBrowseActionPerformed
        if ("BROWSE".equals(evt.getActionCommand())) { //NOI18N
            JFileChooser chooser = new JFileChooser();
            chooser.setCurrentDirectory(null);
            chooser.setDialogTitle(Bundle.TIT_Select_Project_Location());
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            String path = tfProjectLocation.getText();
            if (path.length() > 0) {
                File f = new File(path);
                if (f.exists()) {
                    chooser.setSelectedFile(f);
                }
            }
            if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) {
                File projectDir = chooser.getSelectedFile();
                tfProjectLocation.setText(FileUtil.normalizeFile(projectDir).getAbsolutePath());
            }

        }
    }//GEN-LAST:event_btBrowseActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btBrowse;
    private javax.swing.JCheckBox cbInitWrapper;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel lbDescription;
    private javax.swing.JLabel lbGroup;
    private javax.swing.JLabel lbPackageBase;
    private javax.swing.JLabel lbProjectFolder;
    private javax.swing.JLabel lbProjectLocation;
    private javax.swing.JLabel lbProjectName;
    private javax.swing.JLabel lbVersion;
    javax.swing.JPanel pnlExtraSpace;
    private javax.swing.JTextField tfDescription;
    private javax.swing.JTextField tfGroup;
    private javax.swing.JTextField tfPackageBase;
    private javax.swing.JTextField tfProjectFolder;
    private javax.swing.JTextField tfProjectLocation;
    private javax.swing.JTextField tfProjectName;
    private javax.swing.JTextField tfVersion;
    // End of variables declaration//GEN-END:variables

    @Override
    public void insertUpdate(DocumentEvent e) {
        updateTextFields(e);
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        updateTextFields(e);
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        updateTextFields(e);
    }

    private void updateTextFields(DocumentEvent e) {
        Document doc = e.getDocument();

        if (tfProjectName.getDocument() == doc || tfProjectLocation.getDocument() == doc) {
            File location = new File(tfProjectLocation.getText());
            if (location.isDirectory()) {
                tfProjectFolder.setText(tfProjectLocation.getText() + File.separator + tfProjectName.getText());
            } else {
                tfProjectFolder.setText(tfProjectLocation.getText());
            }
        }

        if (!changedPackageBase && (tfProjectName.getDocument() == doc || tfGroup.getDocument() == doc)) {
            String part1 = tfGroup.getText().trim();
            part1 = !part1.isEmpty() ? part1 + "." : part1;

            String part2 = tfProjectName.getText().trim().replace(" ", "").replace('-', '.');
            tfPackageBase.getDocument().removeDocumentListener(this);
            tfPackageBase.setText(part1 + part2);
            tfPackageBase.getDocument().addDocumentListener(this);
        }

        if (tfPackageBase.getDocument() == doc) {
            changedPackageBase = !tfPackageBase.getText().trim().isEmpty();
        }

        if (tfProjectName.getDocument() == doc) {
            firePropertyChange(PROP_PROJECT_NAME, null, tfProjectName.getText());
        }
    }

    void read(WizardDescriptor settings) {
        File loc = (File) settings.getProperty(CommonProjectActions.PROJECT_PARENT_FOLDER);
        if (loc == null || loc.getParentFile() == null || !loc.getParentFile().isDirectory()) {
            loc = ProjectChooser.getProjectsFolder();
        }
        tfProjectLocation.setText(loc.getAbsolutePath());

        String name = (String) settings.getProperty(PROP_NAME);

        name = name != null ? name : firstAvailableName(loc, "gradleproject"); //NOI18N
        tfProjectName.setText(name);

        setText(tfGroup, settings, PROP_GROUP);
        setText(tfVersion, settings, PROP_VERSION);
        setText(tfDescription, settings, PROP_DESCRIPTION);
        setText(tfPackageBase, settings, PROP_PACKAGE_BASE);

        Boolean initWrapper = (Boolean) settings.getProperty(PROP_INIT_WRAPPER);
        cbInitWrapper.setSelected(initWrapper != null ? initWrapper : true);

        Boolean changedPkg = (Boolean) settings.getProperty(PROP_CHANGED_PKG);
        changedPackageBase = changedPkg == null ? false : changedPkg;

        tfProjectName.selectAll();

    }

    void write(WizardDescriptor settings) {
        File projectFolder = new File(tfProjectLocation.getText());
        ProjectChooser.setProjectsFolder(projectFolder);
        settings.putProperty(CommonProjectActions.PROJECT_PARENT_FOLDER,
                projectFolder);
        settings.putProperty(PROP_NAME, tfProjectName.getText());
        settings.putProperty(PROP_GROUP, tfGroup.getText());
        settings.putProperty(PROP_VERSION, tfVersion.getText());
        settings.putProperty(PROP_DESCRIPTION, tfDescription.getText());
        settings.putProperty(PROP_PACKAGE_BASE, tfPackageBase.getText());
        settings.putProperty(PROP_CHANGED_PKG, changedPackageBase);
        settings.putProperty(PROP_INIT_WRAPPER, cbInitWrapper.isSelected());
    }

    private static void setText(JTextComponent c, WizardDescriptor settings, String prop) {
        String value = (String) settings.getProperty(prop);
        if (value != null) {
            c.setText(value);
        }
    }

    private static String firstAvailableName(File dir, String baseName) {
        int index = 1;
        String name;
        File folder;
        do {
            name = baseName + String.valueOf(index++);
            folder = new File(dir, name);
        } while (folder.exists());
        return name;
    }
}
