/*
 * 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.maven.jaxws.nodes;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.TypeElement;
import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.modules.maven.api.execute.RunConfig;
import org.netbeans.modules.maven.api.execute.RunUtils;
import org.netbeans.modules.maven.jaxws.MavenModelUtils;
import org.netbeans.modules.maven.model.ModelOperation;
import org.netbeans.modules.maven.model.pom.POMModel;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsComponentFactory;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsHandler;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsHandlerChain;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsHandlerChains;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsHandlerClass;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsModel;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsModelFactory;
import org.netbeans.modules.websvc.api.jaxws.bindings.DefinitionsBindings;
import org.netbeans.modules.websvc.api.jaxws.bindings.GlobalBindings;
import org.netbeans.modules.websvc.jaxws.light.api.JaxWsService;
import org.netbeans.modules.websvc.spi.support.MessageHandlerPanel;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModel;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlService;
import org.netbeans.modules.websvc.api.jaxws.bindings.BindingsHandlerName;
import org.netbeans.modules.xml.xam.ModelSource;
import org.netbeans.modules.xml.retriever.catalog.Utilities;
import org.openide.ErrorManager;
import org.openide.NotifyDescriptor;
import org.openide.cookies.SaveCookie;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.netbeans.modules.websvc.api.support.java.SourceUtils;
import org.netbeans.modules.websvc.jaxws.light.api.JAXWSLightSupport;

/**
 *
 * @author Roderico Cruz
 */
public class ClientHandlerButtonListener implements ActionListener {

    private MessageHandlerPanel panel;
    private BindingsModel bindingsModel;
    private JaxWsService client;
    private Node node;
//    private JaxWsModel jaxWsModel;
    //private FileObject bindingHandlerFO;
    private String bindingsHandlerFile;

    public ClientHandlerButtonListener(MessageHandlerPanel panel,
            BindingsModel bindingsModel, JaxWsService client, Node node) {

        this.panel = panel;
        this.bindingsModel = bindingsModel;
        this.client = client;
        this.node = node;
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
        if (evt.getSource() == NotifyDescriptor.OK_OPTION) {
            RequestProcessor.getDefault().post(new Runnable() {

                @Override
                public void run() {
                    configureHandler();
                }
            });
        }
    }

    private void configureHandler() {
        if (!panel.isChanged()) {
            return;
        }
        ProgressHandle handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(ClientHandlerButtonListener.class, "MSG_ConfigureHandler")); //NOI18N
        handle.start();
        handle.switchToIndeterminate();
        JAXWSLightSupport support = node.getLookup().lookup(JAXWSLightSupport.class);
        FileObject bindingsFolder = support.getBindingsFolder(true);
        assert client != null;

        try {
            bindingsHandlerFile = client.getHandlerBindingFile();
            if (bindingsHandlerFile == null) {
                String baseBindingsHandlerFile = node.getName() + "_handler";
                bindingsHandlerFile = FileUtil.findFreeFileName(bindingsFolder, baseBindingsHandlerFile, "xml") +
                        ".xml";
                client.setHandlerBindingFile(bindingsHandlerFile);
            }
            final FileObject bindingHandlerFO = FileUtil.createData(bindingsFolder, bindingsHandlerFile);
            //if bindingsModel is null, create it
            if (bindingsModel == null) {
                InputStream is = FileUtil.getConfigFile("jax-ws/default-binding-handler.xml").getInputStream();
                final String bindingsContent = readResource(is); //NOI18N
                is.close();

                bindingsFolder.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {

                    @Override
                    public void run() throws IOException {
                        BufferedWriter bw = null;
                        OutputStream os = null;
                        OutputStreamWriter osw = null;
                        FileLock lock = bindingHandlerFO.lock();
                        try {
                            os = bindingHandlerFO.getOutputStream(lock);
                            osw = new OutputStreamWriter(os, Charset.forName("UTF-8")); //  NOI18N
                            bw = new BufferedWriter(osw);
                            bw.write(bindingsContent);
                        } finally {
                            try {
                                if (bw != null) {
                                    bw.close();
                                }
                                if (os != null) {
                                    os.close();
                                }
                                if (osw != null) {
                                    osw.close();
                                }
                            } catch (IOException e) {
                                ErrorManager.getDefault().notify(e);
                            }

                            if (lock != null) {
                                lock.releaseLock();
                            }
                        }
                    }
                });

                //now load the model and add the entry
                ModelSource ms = Utilities.getModelSource(bindingHandlerFO, true);
                bindingsModel = BindingsModelFactory.getDefault().getModel(ms);
                //get the relative path of the wsdl
                FileObject localWsdlFile =
                        support.getWsdlFolder(false).getFileObject(client.getLocalWsdl());
                File f = FileUtil.toFile(bindingHandlerFO);
                String relativePath = Utilities.relativize(f.toURI(), new URI(localWsdlFile.getURL().toExternalForm()));
                GlobalBindings gb = bindingsModel.getGlobalBindings();
                try {
                    bindingsModel.startTransaction();
                    gb.setWsdlLocation(relativePath);
                } finally {
                    try {
                        bindingsModel.endTransaction();  //becomes locked here
                    } catch (IllegalStateException ex) {
                        ErrorManager.getDefault().notify(ex);
                        return;
                    }
                }

                DataObject dobj = DataObject.find(bindingHandlerFO);
                if (dobj.isModified()) {
                    SaveCookie saveCookie = dobj.getCookie(SaveCookie.class);
                    saveCookie.save();
                }

            }//end if bindingsModel == null

            //get handler chain
            TableModel tableModel = panel.getHandlerTableModel();
            GlobalBindings gb = bindingsModel.getGlobalBindings();
            DefinitionsBindings db = gb.getDefinitionsBindings();
            BindingsHandlerChains bhc = db.getHandlerChains();
            BindingsHandlerChain chain = bhc.getHandlerChains().iterator().next();

            //refresh handlers
            try {
                bindingsModel.startTransaction();
                Collection<BindingsHandler> handlers = chain.getHandlers();
                for (BindingsHandler handler : handlers) {
                    chain.removeHandler(handler);
                }

                if (tableModel.getRowCount() > 0) {
                    BindingsComponentFactory factory = bindingsModel.getFactory();
                    for (int i = 0; i < tableModel.getRowCount(); i++) {
                        String className = (String) tableModel.getValueAt(i, 0);
                        BindingsHandler handler = factory.createHandler();

                        String handlerName = className.substring(className.indexOf(".") + 1);
                        BindingsHandlerName name = factory.createHandlerName();
                        name.setHandlerName(handlerName);
                        handler.setHandlerName(name);

                        BindingsHandlerClass handlerClass = factory.createHandlerClass();
                        handlerClass.setClassName(className);
                        handler.setHandlerClass(handlerClass);

                        chain.addHandler(handler);
                    }
                }
            } finally {
                try {
                    bindingsModel.endTransaction();
                } catch (IllegalStateException ex) {
                    ErrorManager.getDefault().notify(ex);
                }
            }

            //save bindingshandler file
            DataObject dobj = DataObject.find(bindingHandlerFO);
            if (dobj.isModified()) {
                SaveCookie saveCookie = dobj.getCookie(SaveCookie.class);
                saveCookie.save(); //becomes false here
            }

            // adding binding file to 
            Project project = FileOwnerQuery.getOwner(bindingHandlerFO);
            if (project != null) {
                JaxWsClientNode clientNode = node.getLookup().lookup(JaxWsClientNode.class);
                final FileObject wsdlFo = clientNode.getLocalWsdl();
                ModelOperation<POMModel> oper = new ModelOperation<POMModel>() {
                    @Override
                    public void performOperation(POMModel model) {
                        MavenModelUtils.addBindingFile(model, wsdlFo.getName(), bindingsHandlerFile);
                    }
                };
                FileObject pom = project.getProjectDirectory().getFileObject("pom.xml"); //NOI18N
                org.netbeans.modules.maven.model.Utilities.performPOMModelOperations(
                        pom, Collections.singletonList(oper));

                // execute wsimport goal
                RunConfig cfg = RunUtils.createRunConfig(FileUtil.toFile(project.getProjectDirectory()), project, "wsimport", //NOI18N
                        Collections.singletonList("compile")); //NOI18N
                RunUtils.executeMaven(cfg);
            }

        } catch (Exception e) {
            ErrorManager.getDefault().notify(e);
        }
        handle.finish();

    }

    private void removeHandlerAnnotation() {
        JaxWsClientNode clientNode = node.getLookup().lookup(JaxWsClientNode.class);
        WsdlModel wsdlModel = clientNode.getWsdlModel();
        WsdlService service = wsdlModel.getServices().get(0);
        String serviceName = service.getJavaName();
        Project project = FileOwnerQuery.getOwner(clientNode.getLocalWsdl());
        
        SourceGroup[] groups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        ClassPath cp = ClassPath.getClassPath(groups[0].getRootFolder(), ClassPath.SOURCE);
        final FileObject serviceFO = cp.findResource(serviceName.replaceAll("\\.", "/")  + ".java");  //NOI18N

        //if serviceFO is null, the Service interface has not been generated, so no need to remove any annotation
        if(serviceFO == null) return;

        final JavaSource javaSource = JavaSource.forFileObject(serviceFO);
        final CancellableTask<WorkingCopy> modificationTask = new CancellableTask<WorkingCopy>() {

            @Override
            public void run(WorkingCopy workingCopy) throws IOException {
                workingCopy.toPhase(Phase.RESOLVED);
                TreeMaker make = workingCopy.getTreeMaker();
                TypeElement typeElement = SourceUtils.getPublicTopLevelElement(workingCopy);
                ClassTree javaClass = workingCopy.getTrees().getTree(typeElement);

                AnnotationTree handlerAnnotation = null;
                List<? extends AnnotationTree> annots = javaClass.getModifiers().getAnnotations();
                for (AnnotationTree an : annots) {
                    IdentifierTree ident = (IdentifierTree) an.getAnnotationType();
                    TreePath anTreePath = workingCopy.getTrees().getPath(workingCopy.getCompilationUnit(), ident);
                    TypeElement anElement = (TypeElement) workingCopy.getTrees().getElement(anTreePath);
                    if (anElement != null && anElement.getQualifiedName().contentEquals("javax.jws.HandlerChain")) {  //NOI18N
                        handlerAnnotation = an;
                        break;
                    }
                }
                ModifiersTree modifiers = javaClass.getModifiers();
                ModifiersTree newModifiers = make.removeModifiersAnnotation(modifiers, handlerAnnotation);
                workingCopy.rewrite(modifiers, newModifiers);
                CompilationUnitTree compileUnitTree = workingCopy.getCompilationUnit();
                List<? extends ImportTree> imports = compileUnitTree.getImports();
                for (ImportTree imp : imports) {
                    Tree impTree = imp.getQualifiedIdentifier();
                    TreePath impTreePath = workingCopy.getTrees().getPath(workingCopy.getCompilationUnit(), impTree);
                    TypeElement impElement = (TypeElement) workingCopy.getTrees().getElement(impTreePath);
                    if (impElement != null && impElement.getQualifiedName().contentEquals("javax.jws.HandlerChain")) {  //NOI18N
                        CompilationUnitTree newCompileUnitTree = make.removeCompUnitImport(compileUnitTree, imp);
                        workingCopy.rewrite(compileUnitTree, newCompileUnitTree);
                        break;
                    }
                }
            }

            @Override
            public void cancel() {
            }
        };
        if (SwingUtilities.isEventDispatchThread()) {
            RequestProcessor.getDefault().post(new Runnable() {

                @Override
                public void run() {
                    try {
                        javaSource.runModificationTask(modificationTask).commit();
                        saveFile(serviceFO);
                    } catch (IOException ex) {
                        ErrorManager.getDefault().notify(ex);
                    }
                }
            });
        } else {
            try {
                javaSource.runModificationTask(modificationTask).commit();
                saveFile(serviceFO);
            } catch (IOException ex) {
                ErrorManager.getDefault().notify(ex);
            }
        }
    }

    private static void saveFile(FileObject file) throws IOException {
        DataObject dataObject = DataObject.find(file);
        if (dataObject != null) {
            SaveCookie cookie = dataObject.getCookie(SaveCookie.class);
            if (cookie != null) {
                cookie.save();
            }
        }
    }


//TODO: close all streams properly
    private static String readResource(InputStream is) throws IOException {
        // read the config from resource first
        BufferedReader br = null;
        InputStreamReader isr = null;
        StringBuilder sb = new StringBuilder();
        try {
            String lineSep = System.getProperty("line.separator");//NOI18N
            isr = new InputStreamReader(is, Charset.forName("UTF-8"));
            br = new BufferedReader(isr);

            String line = br.readLine();
            while (line != null) {
                sb.append(line);
                sb.append(lineSep);
                line = br.readLine();
            }
        } finally {
            if ( isr!= null ){
                isr.close();
            }
            if ( br!= null ){
                br.close();
            }
            if ( is!= null ){
                is.close();
            }
        }
        return sb.toString();
    }
}
