/*
 * 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.
 */
/*
 * Contributor(s): theanuradha@netbeans.org
 */
package org.netbeans.modules.maven.repository;

import java.awt.Image;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.io.IOException;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.api.progress.aggregate.AggregateProgressFactory;
import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
import org.netbeans.api.progress.aggregate.ProgressContributor;
import org.netbeans.modules.maven.indexer.api.NBVersionInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryUtil;
import org.netbeans.modules.maven.api.CommonArtifactActions;
import org.netbeans.modules.maven.api.FileUtilities;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.embedder.exec.ProgressTransferListener;
import org.netbeans.modules.maven.indexer.api.RepositoryIndexer;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.netbeans.modules.maven.indexer.api.ui.ArtifactViewer;
import org.netbeans.modules.maven.repository.dependency.AddAsDependencyAction;
import org.netbeans.modules.maven.spi.nodes.NodeUtils;
import org.openide.actions.CopyAction;
import org.openide.actions.OpenAction;
import org.openide.cookies.OpenCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import static org.netbeans.modules.maven.repository.Bundle.*;
import org.netbeans.modules.maven.spi.IconResources;
import org.openide.util.datatransfer.ExTransferable;

/**
 *
 * @author mkleint
 * @author Anuradha
 */
public class VersionNode extends AbstractNode {

    private static final RequestProcessor RP = new RequestProcessor(VersionNode.class);

    private NBVersionInfo record;
    private boolean hasJavadoc;
    private boolean hasSources;
    private RepositoryInfo info;
    private FileObject localArtifact;

    private static String toolTipJavadoc = "<img src=\"" + IconResources.class.getClassLoader().getResource(IconResources.JAVADOC_BADGE_ICON) + "\">&nbsp;" //NOI18N
            + NbBundle.getMessage(VersionNode.class, "ICON_JavadocBadge");//NOI18N
    private static String toolTipSource = "<img src=\"" + IconResources.class.getClassLoader().getResource(IconResources.SOURCE_BADGE_ICON) + "\">&nbsp;" //NOI18N
            + NbBundle.getMessage(VersionNode.class, "ICON_SourceBadge");//NOI18N

    private static FileObject findLocalArtifact(RepositoryInfo info, NBVersionInfo record) {
        // XXX should perhaps use info.repositoryPath when available (in case there are multiple local repos)
        return FileUtil.toFileObject(FileUtilities.convertArtifactToLocalRepositoryFile(RepositoryUtil.createArtifact(record)));
    }

    private static Children createChildren(FileObject fo) {
        if (fo != null) {
            try {
                Node n = DataObject.find(fo).getNodeDelegate();
                if (!n.isLeaf()) { // using n.cloneNode().getChildren() does not work; someone caches cloneNode??
                    return new FilterNode.Children(n);
                }
            } catch (DataObjectNotFoundException x) {
                Exceptions.printStackTrace(x);
            }
        }
        return Children.LEAF;
    }

    public VersionNode(RepositoryInfo info, NBVersionInfo versionInfo, boolean javadoc, boolean source, boolean dispNameShort) {
        this(info, versionInfo, findLocalArtifact(info, versionInfo), javadoc, source, dispNameShort);
    }
    private VersionNode(RepositoryInfo info, NBVersionInfo versionInfo, FileObject localArtifact, boolean javadoc, boolean source, boolean dispNameShort) {
        super(createChildren(localArtifact));
        this.info = info;
        hasJavadoc = javadoc;
        hasSources = source;
        this.record = versionInfo;
        setName(versionInfo.getVersion());
        if (dispNameShort) {
            setDisplayName(versionInfo.getVersion() + " [ " + (versionInfo.getType() != null ? versionInfo.getType() : "jar") //NOI18N
                    + (versionInfo.getClassifier() != null ? ("," + versionInfo.getClassifier()) : "") + " ]");//NOI18N
        } else {
            setDisplayName(versionInfo.getGroupId() + ":" + versionInfo.getArtifactId() + ":" + versionInfo.getVersion()); //NOI18N
        }
        setIconBaseWithExtension(IconResources.ICON_DEPENDENCY_JAR);
        setLocalArtifact(localArtifact);
    }

    private void setLocalArtifact(FileObject localArtifact) {
        if (localArtifact != null && localArtifact.isData()) {
            try {
                OpenCookie oc = DataObject.find(NodeUtils.readOnlyLocalRepositoryFile(localArtifact)).getLookup().lookup(OpenCookie.class);
                if (oc != null) {
                    getCookieSet().add(oc);
                }
            } catch (DataObjectNotFoundException x) {
                Exceptions.printStackTrace(x);
            }
        }
        this.localArtifact = localArtifact;
    }

    @Override
    public boolean canCopy() {
        return true;
    }

    @Override
    public Transferable clipboardCopy() throws IOException {
        Transferable deflt = super.clipboardCopy();
        ExTransferable enriched = ExTransferable.create(deflt);
        ExTransferable.Single ex = new ExTransferable.Single(DataFlavor.stringFlavor) {
            @Override
            protected Object getData() {
                return "<dependency>\n" + //NOI18N
                        "  <groupId>" + record.getGroupId() + "</groupId>\n" + //NOI18N
                        "  <artifactId>" + record.getArtifactId() + "</artifactId>\n" + //NOI18N
                        "  <version>" + record.getVersion() + "</version>\n" + //NOI18N
                        "</dependency>"; //NOI18N
            }
        };
        enriched.put(ex);
        return enriched;
    }

    @Override
    public Action[] getActions(boolean context) {
        Artifact artifact = RepositoryUtil.createArtifact(record);
        List<Action> actions = new ArrayList<Action>();
        actions.add(new ShowArtifactAction(record));
        actions.add(new AddAsDependencyAction(artifact));
        actions.add(CommonArtifactActions.createFindUsages(artifact));
        actions.add(CommonArtifactActions.createViewJavadocAction(artifact));
        actions.add(OpenAction.get(OpenAction.class));
        actions.add(new DownloadAction(artifact));
        actions.add(new DownloadAction(artifact, false));
        actions.add(new DownloadAction(artifact, true));
        actions.add(CopyAction.get(CopyAction.class));
        return actions.toArray(new Action[actions.size()]);
    }

    @Override
    public Action getPreferredAction() {
        return new ShowArtifactAction(record);
    }

    @Override
    public Image getIcon(int param) {
        java.awt.Image retValue = super.getIcon(param);
        if (hasJavadoc) {
            Image ann = ImageUtilities.loadImage(IconResources.JAVADOC_BADGE_ICON); //NOI18N
            ann = ImageUtilities.addToolTipToImage(ann, toolTipJavadoc);
            retValue = ImageUtilities.mergeImages(retValue, ann, 12, 0);//NOI18N
        }
        if (hasSources) {
            Image ann = ImageUtilities.loadImage(IconResources.SOURCE_BADGE_ICON); //NOI18N
            ann = ImageUtilities.addToolTipToImage(ann, toolTipSource);
            retValue = ImageUtilities.mergeImages(retValue, ann, 12, 8);//NOI18N
        }
        return retValue;

    }

    @Override
    public Image getOpenedIcon(int param) {
        return getIcon(param);
    }

    @Override
    public String getShortDescription() {
        StringBuffer buffer = new StringBuffer();
        if (record != null) {
            buffer.append("<html>").append(NbBundle.getMessage(VersionNode.class, "TXT_GroupId")).append("<b>").append(record.getGroupId()).append("</b><p>");//NOI18N
            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_ArtifactId")).append("<b>").append(record.getArtifactId()).append("</b><p>");//NOI18N
            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_Version")).append("<b>").append(record.getVersion().toString()).append("</b><p>");//NOI18N
            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_Repository")).append("<b>").append(record.getRepoId()).append("</b><p>");//NOI18N            
            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_Packaging")).append("<b>").append(record.getPackaging()).append("</b><p>");//NOI18N
            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_Name")).append(record.getProjectName()).append("<p>");//NOI18N
//            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_HasJavadoc")).append(hasJavadoc ? NbBundle.getMessage(VersionNode.class, "TXT_true") : NbBundle.getMessage(VersionNode.class, "TXT_false")).append("<p>");//NOI18N
//            buffer.append(NbBundle.getMessage(VersionNode.class, "TXT_HasSources")).append(hasSources ? NbBundle.getMessage(VersionNode.class, "TXT_true") : NbBundle.getMessage(VersionNode.class, "TXT_false"));//NOI18N
//            buffer.append("</html>");//NOI18N
        }
        return buffer.toString();
    }

    private static class ShowArtifactAction extends AbstractAction {
        private NBVersionInfo info;
        ShowArtifactAction(NBVersionInfo info) {
            this.info = info;
            putValue(NAME, NbBundle.getMessage(VersionNode.class, "ACT_View_Details"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            ArtifactViewer.showArtifactViewer(info);
        }
    }

    private class DownloadAction extends AbstractAction {
        private final Artifact art;
        private final boolean primary;
        @Messages("DownloadAction_label=Download")
        DownloadAction(Artifact art) {
            super(DownloadAction_label());
            this.art = art;
            primary = true;
            setEnabled(localArtifact == null && info.isRemoteDownloadable());
        }
        @Messages({
            "DownloadAction_sources_label=Download Sources",
            "DownloadAction_javadoc_label=Download Javadoc"
        })
        DownloadAction(Artifact primaryArt, boolean javadoc) {
            super(javadoc ? DownloadAction_javadoc_label() : DownloadAction_sources_label());
            art = EmbedderFactory.getProjectEmbedder().createArtifactWithClassifier(primaryArt.getGroupId(), primaryArt.getArtifactId(), primaryArt.getVersion(), "jar", javadoc ? "javadoc" : "sources");
            primary = false;
            setEnabled((javadoc ? hasJavadoc : hasSources) && info.isRemoteDownloadable() && !FileUtilities.convertArtifactToLocalRepositoryFile(art).isFile());
        }
        @Messages({"# {0} - artifact ID", "DownloadAction_downloading=Downloading {0}"})
        public @Override void actionPerformed(ActionEvent e) {
            RP.post(new Runnable() {
                public @Override void run() {
                    MavenEmbedder online = EmbedderFactory.getOnlineEmbedder();
                    AggregateProgressHandle hndl = AggregateProgressFactory.createHandle(DownloadAction_downloading(art.getId()),
                            new ProgressContributor[] {AggregateProgressFactory.createProgressContributor("")},
                            ProgressTransferListener.cancellable(), null);
                    ProgressTransferListener.setAggregateHandle(hndl);
                    try {
                        hndl.start();
                        //mkleint: XXX theoretically using info from RepositoryPreferences.getRepositoryInfos() here could cause problems as the 
                        // maven embedder code might want to retry applying mirrors on it.
                        online.resolve(art, Collections.<ArtifactRepository>singletonList(online.createRemoteRepository(info.getRepositoryUrl(), info.getId())), online.getLocalRepository());
                    } catch (ThreadDeath d) {
                        return;
                    } catch (IllegalStateException ise) { //download interrupted in dependent thread. #213812
                        if (!(ise.getCause() instanceof ThreadDeath)) {
                            throw ise;
                        }
                        return;
                    } catch (AbstractArtifactResolutionException x) {
                        return;
                    } finally {
                        hndl.finish();
                        ProgressTransferListener.clearAggregateHandle();
                    }
                    if (!primary) {
                        return;
                    }
                    RepositoryIndexer.updateIndexWithArtifacts(RepositoryPreferences.getInstance().getLocalRepository(), Collections.singletonList(art));
                    setLocalArtifact(findLocalArtifact(info, record));
                    setChildren(createChildren(localArtifact));
                }
            });
        }
    }

}
