/*
 * 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.
 */

/*
 * FormatPanel.java
 *
 * Created on Jan 9, 2009, 5:12:31 PM
 */

package org.netbeans.modules.bugtracking.vcs;

import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.netbeans.modules.bugtracking.vcs.VCSHooksConfig.Format;
import org.openide.util.NbBundle;

/**
 *
 * @author Tomas Stupka
 */
public class FormatPanel extends javax.swing.JPanel{
    private final Format defaultIssueInfoTemplate;
    private final Format defaultRevisionTemplate;
    private final String[] supportedIssueInfoVariables;
    private final String[] supportedRevisionVariables;

    /** Creates new form FormatPanel */
    FormatPanel(
            Format revisionTemplate,
            Format defaultRevisionTemplate,
            String[] supportedRevisionVariables,
            Format issueInfoTemplate,
            Format defaultIssueInfoTemplate,
            String[] supportedIssueInfoVariables)
    {
        initComponents();
        warningLabel.setVisible(false);
        
        this.defaultIssueInfoTemplate = defaultIssueInfoTemplate;
        this.supportedIssueInfoVariables = supportedIssueInfoVariables;
        this.defaultRevisionTemplate = defaultRevisionTemplate;
        this.supportedRevisionVariables = supportedRevisionVariables;
        setRevisionTemplate(revisionTemplate);
        setIssueInfoTemplate(issueInfoTemplate);

        issueInfoTextArea.getDocument().addDocumentListener(new MsgListener(issueInfoTextArea));
        revisionTextArea.getDocument().addDocumentListener(new MsgListener(revisionTextArea));
    }

    Format getCommitFormat() {
        return new Format(aboveCommitRadio.isSelected(), issueInfoTextArea.getText());
    }

    Format getIssueFormat() {
        return new Format(false, revisionTextArea.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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        buttonGroup2 = new javax.swing.ButtonGroup();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        issueInfoTextArea = new javax.swing.JTextArea();
        jLabel2 = new javax.swing.JLabel();
        aboveCommitRadio = new javax.swing.JRadioButton();
        belowCommitRadio = new javax.swing.JRadioButton();
        resetCommitButton = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        revisionTextArea = new javax.swing.JTextArea();
        resetIssueButton = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        warningLabel = new javax.swing.JLabel();
        placeholder = new javax.swing.JLabel();

        jLabel1.setLabelFor(issueInfoTextArea);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.jLabel1.text")); // NOI18N

        issueInfoTextArea.setColumns(20);
        issueInfoTextArea.setFont(new java.awt.Font("Monospaced", 0, 13));
        issueInfoTextArea.setRows(5);
        issueInfoTextArea.setToolTipText(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.issueInfoTextArea.toolTipText")); // NOI18N
        jScrollPane1.setViewportView(issueInfoTextArea);
        issueInfoTextArea.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.jTextArea1.AccessibleContext.accessibleDescription")); // NOI18N

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

        buttonGroup1.add(aboveCommitRadio);
        org.openide.awt.Mnemonics.setLocalizedText(aboveCommitRadio, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.aboveCommitRadio.text")); // NOI18N

        buttonGroup1.add(belowCommitRadio);
        org.openide.awt.Mnemonics.setLocalizedText(belowCommitRadio, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.belowCommitRadio.text")); // NOI18N
        belowCommitRadio.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                belowCommitRadioActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(resetCommitButton, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.resetCommitButton.text")); // NOI18N
        resetCommitButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetCommitButtonActionPerformed(evt);
            }
        });

        jLabel3.setLabelFor(revisionTextArea);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.jLabel3.text")); // NOI18N

        revisionTextArea.setColumns(20);
        revisionTextArea.setFont(new java.awt.Font("Monospaced", 0, 13));
        revisionTextArea.setRows(5);
        revisionTextArea.setToolTipText(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.revisionTextArea.toolTipText")); // NOI18N
        jScrollPane2.setViewportView(revisionTextArea);

        org.openide.awt.Mnemonics.setLocalizedText(resetIssueButton, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.resetIssueButton.text")); // NOI18N
        resetIssueButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetIssueButtonActionPerformed(evt);
            }
        });

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

        warningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/bugtracking/bridge/resources/warning.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.warningLabel.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(placeholder, org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.placeholder.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)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(aboveCommitRadio)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(resetIssueButton)
                                .addComponent(belowCommitRadio)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 89, Short.MAX_VALUE)
                        .addComponent(resetCommitButton))
                    .addComponent(jLabel4)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 236, Short.MAX_VALUE)
                            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 236, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE)
                            .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(warningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 461, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(placeholder, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jLabel1, 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(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel2)
                            .addComponent(aboveCommitRadio))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(belowCommitRadio)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(resetIssueButton))
                    .addComponent(resetCommitButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(warningLabel)
                    .addComponent(placeholder))
                .addContainerGap())
        );

        aboveCommitRadio.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.aboveRadio.AccessibleContext.accessibleDescription")); // NOI18N
        belowCommitRadio.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.beloveRadio.AccessibleContext.accessibleDescription")); // NOI18N
        resetCommitButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.jButton1.AccessibleContext.accessibleDescription")); // NOI18N
        resetIssueButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.resetIssueButton.AccessibleContext.accessibleDescription")); // NOI18N

        getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FormatPanel.class, "FormatPanel.AccessibleContext.accessibleDescription")); // NOI18N
    }// </editor-fold>//GEN-END:initComponents

    private void belowCommitRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_belowCommitRadioActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_belowCommitRadioActionPerformed

    private void resetCommitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetCommitButtonActionPerformed
        setRevisionTemplate(defaultRevisionTemplate);
    }//GEN-LAST:event_resetCommitButtonActionPerformed

    private void resetIssueButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetIssueButtonActionPerformed
        setIssueInfoTemplate(defaultIssueInfoTemplate);
    }//GEN-LAST:event_resetIssueButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton aboveCommitRadio;
    private javax.swing.JRadioButton belowCommitRadio;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.ButtonGroup buttonGroup2;
    private javax.swing.JTextArea issueInfoTextArea;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel placeholder;
    private javax.swing.JButton resetCommitButton;
    private javax.swing.JButton resetIssueButton;
    private javax.swing.JTextArea revisionTextArea;
    private javax.swing.JLabel warningLabel;
    // End of variables declaration//GEN-END:variables

    private void setRevisionTemplate(Format format) {
        revisionTextArea.setText(format.getFormat());
    }

    private void setIssueInfoTemplate(Format format) {
        issueInfoTextArea.setText(format.getFormat());
        aboveCommitRadio.setSelected(format.isAbove());
        belowCommitRadio.setSelected(!format.isAbove());
    }


    private void validateText(JTextArea textArea) {
        assert textArea == revisionTextArea || textArea == issueInfoTextArea;
        String[] variables = textArea == revisionTextArea ? supportedRevisionVariables : supportedIssueInfoVariables;

        boolean valid = !HookUtils.containsUnsupportedVariables(textArea.getText(), variables);
        warningLabel.setText(NbBundle.getMessage(FormatPanel.class, "FormatPanel.warningLabel.text", list(variables)));
        warningLabel.setVisible(!valid);
    }

    private String list(String[] str) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < str.length; i++) {
            sb.append("{");                                                     // NOI18N
            sb.append(str[i]);
            sb.append("}");                                                     // NOI18N
            if(i < str.length - 1) {
                sb.append(", ");                                                // NOI18N
            }
        }
        return sb.toString();
    }

    private class MsgListener implements DocumentListener {
        private final JTextArea textArea;

        public MsgListener(JTextArea textArea) {
            this.textArea = textArea;
        }

        public void insertUpdate(DocumentEvent e) {
            validateText(textArea);
        }

        public void removeUpdate(DocumentEvent e) {
            validateText(textArea);
        }

        public void changedUpdate(DocumentEvent e) {
            validateText(textArea);
        }

    }
}
