/*
 * 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.project.ui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ListCellRenderer;
import javax.swing.event.ChangeListener;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.project.Project;
import static org.netbeans.modules.project.ui.Bundle.*;
import org.netbeans.modules.project.ui.spi.TemplateCategorySorter;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataShadow;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.AsyncGUIJob;
import org.openide.util.ChangeSupport;
import org.openide.util.NbBundle.Messages;
import org.openide.util.Utilities;

/**
 * Provides the GUI for the template chooser panel.
 * @author Jesse Glick
 */
final class TemplateChooserPanelGUI extends javax.swing.JPanel implements PropertyChangeListener, AsyncGUIJob {
    
    /** preferred dimension of the panels */
    private static final Dimension PREF_DIM = new Dimension(500, 340);
    
    // private final String[] recommendedTypes = null;
    private final ChangeSupport changeSupport = new ChangeSupport(this);

    //Templates folder root
    private FileObject templatesFolder;

    //GUI Builder
    private TemplatesPanelGUI.Builder builder;
    @NullAllowed
    private Project project;
    private @NonNull String[] projectRecommendedTypes;
    private String category;
    private String template;
    private boolean isWarmUp = true;
    private ListCellRenderer projectCellRenderer;
    private boolean firstTime = true;
    private ActionListener defaultActionListener;
    private boolean includeTemplatesWithProjects;

    @Messages("LBL_TemplateChooserPanelGUI_Name=Choose File Type")
    public TemplateChooserPanelGUI(boolean includeTemplatesWithProject) {
        this.builder = new FileChooserBuilder ();
        this.includeTemplatesWithProjects = includeTemplatesWithProject;
        initComponents();
        setPreferredSize( PREF_DIM );
        setName(LBL_TemplateChooserPanelGUI_Name());
        projectCellRenderer = new ProjectCellRenderer ();
        projectsComboBox.setRenderer (projectCellRenderer);
     }
    
    public void readValues (@NullAllowed Project p, String category, String template) {
        boolean wf;
        synchronized (this) {
            this.project = p;
            this.projectRecommendedTypes = OpenProjectList.getRecommendedTypes(p);
            this.category = category;
            this.template = template;
            wf = this.isWarmUp;
        }
        if (!wf) {
            this.selectProject ( project );
            ((TemplatesPanelGUI)this.templatesPanel).setSelectedCategoryByName (this.category);
            ((TemplatesPanelGUI)this.templatesPanel).setSelectedTemplateByName (this.template);
        }
    }

    @Override
    public void removeNotify() {
        super.removeNotify();
        project = null;
    }

    /** Called from readSettings, to initialize the GUI with proper components
     */
    private void initValues( @NullAllowed Project p ) {
        // Populate the combo box with list of projects
        DefaultComboBoxModel projectsModel;
        if (includeTemplatesWithProjects) {
            Project openProjects[] = OpenProjectList.getDefault().getOpenProjects();
            Arrays.sort(openProjects, OpenProjectList.projectByDisplayName());
            projectsModel = new DefaultComboBoxModel( openProjects );
            selectProject(p);
        } else {
            projectsModel = new DefaultComboBoxModel();
        }
        projectsComboBox.setModel( projectsModel );
        projectsComboBox.setEnabled(includeTemplatesWithProjects);
        this.selectProject (p);
    }

    private void selectProject (@NullAllowed Project p) {
        if (p != null) {
            DefaultComboBoxModel projectsModel = (DefaultComboBoxModel) projectsComboBox.getModel ();
            if ( projectsModel.getIndexOf( p ) == -1 ) {
                projectsModel.insertElementAt( p, 0 );
            }
            projectsComboBox.setSelectedItem( p );
        } 
        else {
            projectsComboBox.setSelectedItem(null);
        }
    }


    public void addChangeListener(ChangeListener l) {
        changeSupport.addChangeListener(l);
    }
    
    public void removeChangeListener(ChangeListener l) {
        changeSupport.removeChangeListener(l);
    }
    
    private void fireChange() {
        changeSupport.fireChange();
    }

    void setDefaultActionListener( ActionListener al ) {
        this.defaultActionListener = al;
    }

    @CheckForNull
    public Project getProject() {
        boolean wf;
        synchronized (this) {
            wf = isWarmUp;
        }
        if (wf) {
            return this.project;
        }
        else {
            return (Project)projectsComboBox.getSelectedItem();
        }
    }
    
    public FileObject getTemplate() {
        return ((TemplatesPanelGUI)this.templatesPanel).getSelectedTemplate ();
    }
    
    @Override public void propertyChange(PropertyChangeEvent evt) {
        fireChange();
    }
    
    
    @Override public Dimension getPreferredSize() {
        return PREF_DIM;
    }
    
    public String getCategoryName () {
        return ((TemplatesPanelGUI)this.templatesPanel).getSelectedCategoryName ();
    }

    public String getTemplateName () {
        return ((TemplatesPanelGUI)this.templatesPanel).getSelectedTemplateName ();
    }

    public void setCategory (String category) {
        ((TemplatesPanelGUI)this.templatesPanel).setSelectedCategoryByName (category);
    }
    
    @Override public void addNotify () {
        if (firstTime) {
            //77244 prevent multiple initializations..
            Utilities.attachInitJob (this, this);
            firstTime = false;
        }
        super.addNotify ();
    }
    
    /** 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() {
        java.awt.GridBagConstraints gridBagConstraints;

        jLabel1 = new javax.swing.JLabel();
        projectsComboBox = new javax.swing.JComboBox();
        templatesPanel = new TemplatesPanelGUI (this.builder);

        setLayout(new java.awt.GridBagLayout());

        jLabel1.setLabelFor(projectsComboBox);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(TemplateChooserPanelGUI.class, "LBL_TemplateChooserPanelGUI_jLabel1")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 13, 0);
        add(jLabel1, gridBagConstraints);
        jLabel1.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TemplateChooserPanelGUI.class, "ACSN_jLabel1")); // NOI18N
        jLabel1.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(TemplateChooserPanelGUI.class, "ACSD_jLabel1")); // NOI18N

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 6, 12, 0);
        add(projectsComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(templatesPanel, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JComboBox projectsComboBox;
    private javax.swing.JPanel templatesPanel;
    // End of variables declaration//GEN-END:variables

    // private static final Comparator NATURAL_NAME_SORT = Collator.getInstance();

    private static final class TemplateKey {
        final DataObject d;
        final boolean leaf;
        TemplateKey(DataObject d, boolean leaf) {
            this.d = d;
            this.leaf = leaf;
        }
        @Override public boolean equals(Object o) {
            if (!(o instanceof TemplateKey)) {
                return false;
            }
            return d == ((TemplateKey) o).d && leaf == ((TemplateKey) o).leaf;
        }
        @Override public int hashCode() {
            return d.hashCode();
        }
    }
    private final class TemplateChildren extends ChildFactory.Detachable<TemplateKey> implements ActionListener {
        
        private final DataFolder folder;
        private final boolean isRoot;
        private final String filterText;
        
        TemplateChildren(DataFolder folder, boolean root, String filterText) {
            this.folder = folder;
            isRoot = root;
            this.filterText = filterText;
        }
        
        @Override protected void addNotify() {
            projectsComboBox.addActionListener( this );
        }
        
        @Override protected void removeNotify() {
            projectsComboBox.removeActionListener( this );
        }

        @Override protected boolean createKeys(List<TemplateKey> keys) {
            DataObject[] children = folder.getChildren();
            if (isRoot) {
                Project p = getProject();
                TemplateCategorySorter tcs = p != null ? p.getLookup().lookup(TemplateCategorySorter.class) : null;
                if (tcs != null) {
                    List<DataObject> dobjs = new ArrayList<DataObject>();                    
                    for (DataObject d : children) {
                        if (isFolderOfTemplates(d)) {
                            dobjs.add(d);
                        }
                    }
                    List<DataObject> sorted = tcs.sort(dobjs);
                    assert sorted.size() == dobjs.size() && new HashSet<DataObject>(dobjs).equals(new HashSet<DataObject>(sorted));
                    children = sorted.toArray(new DataObject[children.length]);
                }
            }
            
            for (DataObject d : children) {
                if (isFolderOfTemplates(d)) {
                    boolean leaf = true;
                    for (DataObject child : ((DataFolder) d).getChildren()) {
                        if (isFolderOfTemplates(child)) {
                            leaf = false;
                            break;
                        }
                    }
                    if( null == filterText || hasFilteredFileTemplates(d, filterText) )
                        keys.add(new TemplateKey(d, leaf));
                }
            }
            return true;
        }

        private boolean hasFilteredFileTemplates( DataObject root, String filterText ) {
            boolean res = false;
            if( root instanceof DataFolder ) {
                for (DataObject dobj : ((DataFolder)root).getChildren()) {
                    res = isFilteredFileTemplate( dobj, filterText, project, projectRecommendedTypes );
                    if( !res && dobj instanceof DataFolder ) {
                        res = hasFilteredFileTemplates( dobj, filterText );
                    }
                    if( res )
                        break;
                }
            }
            return res;
        }
        
        @Override protected Node createNodeForKey(TemplateKey k) {
            return new FilterNode(k.d.getNodeDelegate(), k.leaf ? Children.LEAF : Children.create(new TemplateChildren((DataFolder) k.d, false, filterText), true));
        }
        
        @Override public void actionPerformed (ActionEvent event) {
            projectRecommendedTypes = OpenProjectList.getRecommendedTypes(getProject());
            final String cat = getCategoryName ();
            String template =  ((TemplatesPanelGUI)TemplateChooserPanelGUI.this.templatesPanel).getSelectedTemplateName();
            refresh(false);
            setCategory (cat);
            ((TemplatesPanelGUI)TemplateChooserPanelGUI.this.templatesPanel).setSelectedTemplateByName(template);
        }
                
        
        // Private methods -----------------------------------------------------
        
        private boolean isFolderOfTemplates(DataObject d) {
            if (d instanceof DataFolder && !isTemplate((DataFolder)d))  {
                Object o = d.getPrimaryFile().getAttribute("simple"); // NOI18N
                if (o == null || Boolean.TRUE.equals(o)) {
                    boolean hasChildren = hasChildren((Project) projectsComboBox.getSelectedItem(), d);
                    if (hasChildren)
                        return hasChildren;
                    else {
                        for (DataObject child : ((DataFolder) d).getChildren()) {
                            return isFolderOfTemplates(child);
                        }
                    }
                }
            }
            return false;
        }
        
    }
    
    private final class FileChildren extends ChildFactory<DataObject> {
        
        private DataFolder root;
        private final String filterText;
                
        public FileChildren (DataFolder folder, String filterText) {
            this.root = folder;
            assert this.root != null : "Root can not be null";  //NOI18N
            this.filterText = filterText;
        }
        
        @Override protected boolean createKeys(List<DataObject> keys) {
            for (DataObject dobj : root.getChildren()) {
                if( isFilteredFileTemplate( dobj, filterText, project, projectRecommendedTypes ) ) {
                    keys.add(dobj);
                }
            }
            return true;
        }

        @Override protected Node createNodeForKey(DataObject d) {
            return new FilterNode(d.getNodeDelegate(), Children.LEAF);
        }
        
    }

    private static boolean isFilteredFileTemplate( DataObject dobj, String filterText, Project project, String[] projectRecommendedTypes ) {
        boolean res = false;
        if (isTemplate(dobj) && OpenProjectList.isRecommended(project, projectRecommendedTypes, dobj.getPrimaryFile())) {
            if (dobj instanceof DataShadow) {
                dobj = ((DataShadow) dobj).getOriginal();
            }
            res = null == filterText || dobj.getNodeDelegate().getDisplayName().toLowerCase().contains( filterText.toLowerCase() );
        }
        return res;
    }
  
    final class FileChooserBuilder implements TemplatesPanelGUI.Builder {
        
        @Override public Children createCategoriesChildren(DataFolder folder, String filterText) {
            return Children.create(new TemplateChildren(folder, true, filterText), true);
        }
        
        @Override public Children createTemplatesChildren(DataFolder folder, String filterText) {
            return Children.create(new FileChildren(folder, filterText), true);
        }

        @Override public void fireChange() {
            TemplateChooserPanelGUI.this.fireChange();
        }

        @Messages("CTL_Categories=&Categories:")
        @Override public String getCategoriesName() {
            return CTL_Categories();
        }
        
        @Messages("CTL_Files=&File Types:")
        @Override public String getTemplatesName() {
            return CTL_Files();
        }

        @Override
        public void actionPerformed( ActionEvent e ) {
            if( null != defaultActionListener ) {
                defaultActionListener.actionPerformed( e );
            }
        }
    }
    
    
    private static boolean isTemplate (DataObject dobj) {
        if (dobj.isTemplate())
            return true;
        if (dobj instanceof DataShadow) {
            return ((DataShadow)dobj).getOriginal().isTemplate();
        }
        return false;
    }
    
    private boolean hasChildren (Project p, DataObject folder) { 
        if (!(folder instanceof DataFolder)) {
            return false;
        }
        
        DataFolder f = (DataFolder) folder;
        if (!OpenProjectList.isRecommended(p, projectRecommendedTypes, f.getPrimaryFile())) {
            // Eg. Licenses folder.
            //see #102508
            return false;
        }
        DataObject[] ch = f.getChildren ();
        for (int i = 0; i < ch.length; i++) {
            if (isTemplate (ch[i]) && OpenProjectList.isRecommended(p, projectRecommendedTypes, ch[i].getPrimaryFile ())) {
                // XXX: how to filter link to Package template in each java types folder?
                if (!(ch[i] instanceof DataShadow)) {
                    return true;
                }
            } else if (ch[i] instanceof DataFolder && hasChildren (p, ch[i])) {
                return true;
            }
        }
        return false;
        
        // simplied but more counts
        //return new FileChildren (p, (DataFolder) folder).getNodesCount () > 0;
        
    }
    
    @Override public void construct() {
        this.templatesFolder = FileUtil.getConfigFile("Templates");
        ((TemplatesPanelGUI)this.templatesPanel).warmUp(this.templatesFolder);
    }
    
    @Override public void finished() {
        //In the awt
        Cursor cursor = null;
        try {
            Project p;
            String c,t;
            synchronized (this) {
                p = this.project;
                c = this.category;
                t = this.template;
            }
            cursor = TemplateChooserPanelGUI.this.getCursor();
            TemplateChooserPanelGUI.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            initValues( p );
            ((TemplatesPanelGUI)this.templatesPanel).doFinished (this.templatesFolder, c, t);
        } finally {
            synchronized (this) {
                isWarmUp = false;
            }
            if (cursor != null) {
                this.setCursor (cursor);
            }
        }
    }
    
}
