/*
 * 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.j2ee.persistence.wizard.jpacontroller;

import java.io.IOException;
import javax.swing.ComboBoxModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.modules.j2ee.core.api.support.SourceGroups;
import org.netbeans.modules.j2ee.core.api.support.java.JavaIdentifiers;
import org.netbeans.modules.j2ee.persistence.wizard.Util;
import org.netbeans.modules.j2ee.persistence.wizard.fromdb.SourceGroupUISupport;
import org.netbeans.spi.java.project.support.ui.PackageView;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.ChangeSupport;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 * @author  Pavel Buzek
 */
public class JpaControllerSetupPanelVisual extends javax.swing.JPanel implements DocumentListener {
    
    private WizardDescriptor wizard;
    private Project project;
    private JTextComponent packageComboBoxEditor;
    private ChangeSupport changeSupport = new ChangeSupport(this);
    
    /** Creates new form CrudSetupPanel */
    public JpaControllerSetupPanelVisual(WizardDescriptor wizard) {
        this.wizard = wizard;
        initComponents();
        
        packageComboBoxEditor = ((JTextComponent)packageComboBox.getEditor().getEditorComponent());
        Document packageComboBoxDocument = packageComboBoxEditor.getDocument();
        packageComboBoxDocument.addDocumentListener(this);
//        jsfFolder.addKeyListener(new KeyListener(){
//            public void keyPressed(KeyEvent e) {
//                changeSupport.fireChange();
//            }            
//            public void keyReleased(KeyEvent e) {
//                changeSupport.fireChange();
//            } 
//            public void keyTyped(KeyEvent e) {
//                changeSupport.fireChange();
//            }
//        });
    }
    
    /** 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() {

        jLabel4 = new javax.swing.JLabel();
        projectLabel = new javax.swing.JLabel();
        projectTextField = new javax.swing.JTextField();
        locationLabel = new javax.swing.JLabel();
        locationComboBox = new javax.swing.JComboBox();
        packageLabel = new javax.swing.JLabel();
        packageComboBox = new javax.swing.JComboBox();

        setName(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_JpaControllerClasses")); // NOI18N

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/j2ee/persistence/wizard/jpacontroller/Bundle"); // NOI18N
        jLabel4.setText(bundle.getString("MSG_Jpa_Controller_Location")); // NOI18N

        projectLabel.setDisplayedMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/j2ee/persistence/wizard/jpacontroller/Bundle").getString("MNE_Project").charAt(0));
        projectLabel.setLabelFor(projectTextField);
        projectLabel.setText(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Project")); // NOI18N

        projectTextField.setEditable(false);

        locationLabel.setDisplayedMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/j2ee/persistence/wizard/jpacontroller/Bundle").getString("MNE_Location").charAt(0));
        locationLabel.setLabelFor(locationComboBox);
        org.openide.awt.Mnemonics.setLocalizedText(locationLabel, org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_SrcLocation")); // NOI18N

        locationComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                locationComboBoxActionPerformed(evt);
            }
        });

        packageLabel.setDisplayedMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/j2ee/persistence/wizard/jpacontroller/Bundle").getString("MNE_Package").charAt(0));
        packageLabel.setLabelFor(packageComboBox);
        packageLabel.setText(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Package")); // NOI18N

        packageComboBox.setEditable(true);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(projectLabel)
                            .addComponent(locationLabel)
                            .addComponent(packageLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(locationComboBox, javax.swing.GroupLayout.Alignment.TRAILING, 0, 552, Short.MAX_VALUE)
                            .addComponent(projectTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 552, Short.MAX_VALUE)
                            .addComponent(packageComboBox, 0, 552, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jLabel4)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(projectLabel)
                    .addComponent(projectTextField, 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(locationLabel)
                    .addComponent(locationComboBox, 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(packageLabel)
                    .addComponent(packageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(148, Short.MAX_VALUE))
        );

        jLabel4.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "MSG_Jpa_Controller_Location")); // NOI18N
        jLabel4.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "MSG_Jpa_Controller_Location")); // NOI18N
        projectLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Project")); // NOI18N
        projectLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Project")); // NOI18N
        projectTextField.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ACSD_Project")); // NOI18N
        locationLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_SrcLocation")); // NOI18N
        locationLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_SrcLocation")); // NOI18N
        locationComboBox.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ACSD_Location")); // NOI18N
        packageLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Package")); // NOI18N
        packageLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "LBL_Package")); // NOI18N
        packageComboBox.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ACSD_Package")); // NOI18N
    }// </editor-fold>//GEN-END:initComponents

    private void locationComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_locationComboBoxActionPerformed
        locationChanged();
    }//GEN-LAST:event_locationComboBoxActionPerformed
                
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel4;
    private javax.swing.JComboBox locationComboBox;
    private javax.swing.JLabel locationLabel;
    private javax.swing.JComboBox packageComboBox;
    private javax.swing.JLabel packageLabel;
    private javax.swing.JLabel projectLabel;
    private javax.swing.JTextField projectTextField;
    // End of variables declaration//GEN-END:variables
    
    public void addChangeListener(ChangeListener listener) {
        changeSupport.addChangeListener(listener);
    }
    
    boolean valid(WizardDescriptor wizard) {
//        List<Entity> entities = (List<Entity>) wizard.getProperty(WizardProperties.ENTITY_CLASS);
//        String controllerPkg = getPackage();
//        
//        boolean filesAlreadyExist = false;
//        String troubleMaker = "";
//        for (Entity entity : entities) {
//            String entityClass = entity.getClass2();
//            String simpleClassName = JSFClientGenerator.simpleClassName(entityClass);
//            String firstLower = simpleClassName.substring(0, 1).toLowerCase() + simpleClassName.substring(1);
//            String folder = jsfFolder.getText().endsWith("/") ? jsfFolder.getText() : jsfFolder.getText() + "/";
//            folder = folder + firstLower;
//            String controller = controllerPkg + "." + simpleClassName + "Controller";
//            String fqn = getPackage().length() > 0 ? getPackage().replace('.', '/') + "/" + simpleClassName : simpleClassName;
//            if (getLocationValue().getRootFolder().getFileObject(fqn + "Controller.java") != null) {
//                filesAlreadyExist = true;
//                troubleMaker = controllerPkg + "." + simpleClassName + "Controller.java";
//                break;
//            }
//            if (getLocationValue().getRootFolder().getFileObject(fqn + "Converter.java") != null) {
//                filesAlreadyExist = true;
//                troubleMaker = controllerPkg + "." + simpleClassName + "Converter.java";
//                break;
//            }
//        }
//        if (filesAlreadyExist) {
//            wizard.putProperty("WizardPanel_errorMessage",                                  // NOI18N
//                NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "MSG_FilesAlreadyExist", troubleMaker));
//            return false;
//        }
//        wizard.putProperty("WizardPanel_errorMessage", null); // NOI18N
        
            if (Util.isContainerManaged(project)) {
                ClassPath cp = ClassPath.getClassPath(getLocationValue().getRootFolder(), ClassPath.COMPILE);
                ClassLoader cl = cp.getClassLoader(true);
                try {
                    Class.forName("javax.transaction.UserTransaction", false, cl);
                }
                catch (ClassNotFoundException cnfe) {
                    wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ERR_UserTransactionUnavailable"));
                    return false;
                }
                catch (java.lang.UnsupportedClassVersionError err)
                {
//                    wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ERR_UserTransactionJavaVersion"));
//                    return false;
                }
            }
        
//            Sources srcs = (Sources) project.getLookup().lookup(Sources.class);
//            SourceGroup sgWeb[] = srcs.getSourceGroups("doc_root"); //NOI18N fixme(mbohm): move into constant
//            FileObject pagesRootFolder = sgWeb[0].getRootFolder();
//            File pagesRootFolderAsFile = FileUtil.toFile(pagesRootFolder);
//            String jsfFolderText = jsfFolder.getText();
//            try {
//                String canonPath = new File(pagesRootFolderAsFile, jsfFolderText).getCanonicalPath();
//            }
//            catch (IOException ioe) {
//                wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ERR_JsfTargetChooser_InvalidJsfFolder"));
//                return false;
//            }
        
            String packageName = getPackage();
            if (packageName.trim().isEmpty()) { // NOI18N
                wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ERR_JavaTargetChooser_CantUseDefaultPackage"));
                return false;
            }

            if (!JavaIdentifiers.isValidPackageName(packageName)) {
                wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class,"ERR_JavaTargetChooser_InvalidPackage")); //NOI18N
                return false;
            }

            if (!SourceGroups.isFolderWritable(getLocationValue(), packageName)) {
                wizard.putProperty("WizardPanel_errorMessage", NbBundle.getMessage(JpaControllerSetupPanelVisual.class, "ERR_JavaTargetChooser_UnwritablePackage")); //NOI18N
                return false;
            }
            wizard.putProperty("WizardPanel_errorMessage", null); // NOI18N
            return true;
    }
    
    public SourceGroup getLocationValue() {
        return (SourceGroup)locationComboBox.getSelectedItem();
    }

    public String getPackage() {
        return packageComboBoxEditor.getText();
    }

    private void locationChanged() {
        updateSourceGroupPackages();
//        changeSupport.fireChange();
    }
    
    void read(WizardDescriptor settings) {
//        jsfFolder.setText((String) settings.getProperty(WizardProperties.JSF_FOLDER));
        
        project = Templates.getProject(settings);
        FileObject targetFolder = Templates.getTargetFolder(settings);
        
        projectTextField.setText(ProjectUtils.getInformation(project).getDisplayName());

         SourceGroup[] sourceGroups = SourceGroups.getJavaSourceGroups(project);      
         SourceGroupUISupport.connect(locationComboBox, sourceGroups);

        packageComboBox.setRenderer(PackageView.listRenderer());

        updateSourceGroupPackages();

        // set default source group and package cf. targetFolder
//        if (targetFolder != null) {
//            SourceGroup targetSourceGroup = SourceGroupSupport.getFolderSourceGroup(sourceGroups, targetFolder);
//            if (targetSourceGroup != null) {
//                locationComboBox.setSelectedItem(targetSourceGroup);
//                String targetPackage = SourceGroupSupport.getPackageForFolder(targetSourceGroup, targetFolder);
//                if (targetPackage != null) {
//                    packageComboBoxEditor.setText(targetPackage);
//                }
//            }
//            if (FileUtil.isParentOf(WebModule.getWebModule(
//                    targetFolder).getDocumentBase(), targetFolder)) {
//                Sources s = (Sources) Templates.getProject(wizard).getLookup().lookup(Sources.class);
//                SourceGroup[] groups = s.getSourceGroups(WebProjectConstants.TYPE_DOC_ROOT);
//                jsfFolder.setText("/"+JSFConfigUtilities.getResourcePath(groups,targetFolder,'/',true));
//            }
//        }
    }
    
    void store(WizardDescriptor settings) {
//        settings.putProperty(WizardProperties.JSF_FOLDER, jsfFolder.getText());
        String pkg = getPackage();
        settings.putProperty(WizardProperties.JPA_CONTROLLER_PACKAGE, pkg);
//        settings.putProperty(WizardProperties.AJAXIFY_JSF_CRUD, Boolean.valueOf(ajaxifyCheckbox.isSelected()));
        try {
            FileObject fo = getLocationValue().getRootFolder();
            String pkgSlashes = pkg.replace('.', '/');
            FileObject targetFolder = fo.getFileObject(pkgSlashes);
            if (targetFolder == null) {
                targetFolder = FileUtil.createFolder(fo, pkgSlashes);
            }
            Templates.setTargetFolder(settings, targetFolder);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private void updateSourceGroupPackages() {
        SourceGroup sourceGroup = (SourceGroup)locationComboBox.getSelectedItem();
        ComboBoxModel model = PackageView.createListView(sourceGroup);
        if (model.getSelectedItem()!= null && model.getSelectedItem().toString().startsWith("META-INF")
                && model.getSize() > 1) { // NOI18N
            model.setSelectedItem(model.getElementAt(1));
        }
        packageComboBox.setModel(model);
    }
    
    @Override
    public void insertUpdate(DocumentEvent e) {
        changeSupport.fireChange();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        changeSupport.fireChange();
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        changeSupport.fireChange();
    }
    
}
