/*
 * 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.autoupdate.pluginimporter;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.autoupdate.InstallSupport;
import org.netbeans.api.autoupdate.OperationContainer;
import org.netbeans.api.autoupdate.UpdateElement;
import org.netbeans.api.autoupdate.UpdateManager;
import org.netbeans.api.autoupdate.UpdateUnit;
import org.netbeans.api.progress.ProgressHandle;
import org.openide.DialogDisplayer;
import org.openide.LifecycleManager;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.modules.SpecificationVersion;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *
 * @author Jiri Rechtacek
 */
public class PluginImporter {

    private final Collection<UpdateUnit> plugins;
    private boolean inspected = false;
    private Collection<UpdateElement> installed = null;
    private Collection<UpdateElement> toInstall = null;
    private Collection<UpdateElement> toImport = null;
    private Collection<UpdateElement> broken = null;

    private static final String TRACKING_FILE_NAME = "update_tracking"; // NOI18N
    private static final String ELEMENT_MODULE = "module"; // NOI18N
    private static final String ELEMENT_VERSION = "module_version"; // NOI18N
    private static final String ATTR_LAST = "last"; // NOI18N
    private static final String ATTR_FILE_NAME = "name"; // NOI18N
    private static final String MODULES = "Modules"; // NOI18N
    private static final String LAST_MODIFIED = ".lastModified"; // NOI18N

    private static final Logger LOG = Logger.getLogger (PluginImporter.class.getName ());

    public PluginImporter (Collection<UpdateUnit> foundPlugins) {
        plugins = foundPlugins;
    }

    public void reinspect () {
        inspected = false;
        inspect();
    }
    private void inspect () {
        if (inspected) {
            return ;
        }
        long start = System.currentTimeMillis();
        installed = new HashSet<UpdateElement> ();
        toImport = new HashSet<UpdateElement> ();
        toInstall = new HashSet<UpdateElement> ();
        broken = new HashSet<UpdateElement> ();

        Collection<UpdateElement> candidate2import = new HashSet<UpdateElement> ();
        List<UpdateUnit> updateUnits = UpdateManager.getDefault ().getUpdateUnits (UpdateManager.TYPE.MODULE);
        Map<String, UpdateUnit> cnb2uu = new HashMap<String, UpdateUnit> (updateUnits.size ());
        for (UpdateUnit u : updateUnits) {
            cnb2uu.put (u.getCodeName (), u);
        }

        for (UpdateUnit unit : plugins) {

            // save information about plugins on common Update Center
            UpdateUnit remoteUnit = cnb2uu.get (unit.getCodeName ());
            UpdateElement remoteElement = null;
            SpecificationVersion remoteSpec = null;
            if (remoteUnit != null && ! remoteUnit.getAvailableUpdates ().isEmpty ()) {
                remoteElement = remoteUnit.getAvailableUpdates ().get (0);
                remoteSpec = remoteElement.getSpecificationVersion() == null ? null : new SpecificationVersion(remoteElement.getSpecificationVersion());
            }

            if (unit.getInstalled () != null) {
                if (! unit.getAvailableUpdates ().isEmpty ()) {
                    UpdateElement el = unit.getAvailableUpdates ().get (0);
                    if (remoteElement != null) {
                        SpecificationVersion spec = el.getSpecificationVersion () == null ? null : new SpecificationVersion (el.getSpecificationVersion ());
                        if (spec != null && spec.compareTo (remoteSpec) > 0) {
                            candidate2import.add (el);
                        }
                    } else {
                        candidate2import.add (el);
                    }
                }
                installed.add (unit.getInstalled ());
            } else if (unit.isPending()) {
                LOG.log(Level.INFO, "Plugin " + unit.getCodeName() + " is not installed but is in pending state - i.e. will be installed upon restart, skipping");
            } else {
                assert ! unit.getAvailableUpdates ().isEmpty () : "If " + unit + " isn't installed thus has available updates.";
                UpdateElement el = unit.getAvailableUpdates ().get (0);
                if (remoteElement != null) {
                    SpecificationVersion spec = el.getSpecificationVersion () == null ? null : new SpecificationVersion (el.getSpecificationVersion ());
                    if (spec != null && spec.compareTo (remoteSpec) > 0) {
                        candidate2import.add (el);
                    } else {
                        toInstall.add (remoteElement);
                    }
                } else {
                    candidate2import.add (el);
                }
            }
        }
        for (UpdateElement el : candidate2import) {
            OperationContainer<InstallSupport> oc = el.getUpdateUnit ().getInstalled () == null ?
                OperationContainer.createForInstall () :
                OperationContainer.createForUpdate ();
            try {
                OperationContainer.OperationInfo info = oc.add (el);
                oc.add (candidate2import);
                if (isBlacklisted(el)) {
                    LOG.info("Plugin " + el + " is on blacklist thus will not be imported.");
                } else if (info.getBrokenDependencies ().isEmpty ()) {
                    toImport.add (el);
                } else {
                    LOG.log (Level.INFO, "Plugin " + el + // NOI18N
                            " cannot be install because not all dependencies can be match: " + info.getBrokenDependencies ()); // NOI18N
                    broken.add (el);
                }
            } catch (IllegalArgumentException iae) {
                LOG.log (Level.INFO, iae.getLocalizedMessage (), iae);
                broken.add (el);
            }
        }
        long end = System.currentTimeMillis();
        LOG.log (Level.INFO, "Inspecting plugins took " + (end - start) + " ms"); // NOI18N

        inspected = true;
    }

    public Collection<UpdateElement> getPluginsToImport () {
        inspect ();
        return toImport;
    }

    public Collection<UpdateElement> getInstalledPlugins () {
        inspect ();
        return installed;
    }

    public Collection<UpdateElement> getPluginsAvailableToInstall () {
        inspect ();
        return toInstall;
    }

    public Collection<UpdateElement> getBrokenPlugins () {
        inspect ();
        return broken;
    }

    public void importPlugins (Collection<UpdateElement> plugins, File src, File dest, ProgressHandle handle) throws IOException {
        if(handle!=null) {
            handle.setInitialDelay(0);
            handle.start(plugins.size());
        }
        List<String> configs = new ArrayList<String> (plugins.size ());
        int completed = 0;
        for (UpdateElement el : plugins) {
            if(handle != null) {
                String name = el.getDisplayName();
                if(name==null) {
                    name = el.getCodeName();
                }
                String detail = NbBundle.getMessage(PluginImporter.class, "PluginImporter.Importing.Plugin", name);//NOI18N
                handle.progress(detail, completed ++);
            }
            String cnb = el.getCodeName ();

            // 1. find all plugin's resources
            Collection<String> toCopy = getPluginFiles (src, cnb, locateUpdateTracking (cnb, src));
            if (toCopy.isEmpty()) {
                continue;
            }

            // 2. copy them
            for (String path : toCopy) {
                copy (path, src, dest);
            }

            // 3. find config file
            String path = "config/Modules/" + cnb.replace ('.', '-') + ".xml"; // NOI18N
            configs.add (path);
        }

        // 4. find and copy config files in the end
        for (String path : configs) {
            copy (path, src, dest);
        }

        // #252928 (fragment modules)
        if (getPluginsToImport().isEmpty()) {
            refreshModuleList();
        } else {
            String restartMsg = NbBundle.getMessage(PluginImporter.class, "PluginImporter.Importing.RestartNeeded");//NOI18N
            NotifyDescriptor nd = new NotifyDescriptor.Confirmation(restartMsg, NotifyDescriptor.YES_NO_OPTION);
            Object result = DialogDisplayer.getDefault().notify(nd);
            if (result.equals(NotifyDescriptor.OK_OPTION)) {
                LifecycleManager.getDefault().markForRestart();
                LifecycleManager.getDefault().exit();
            }
        }

        if(handle!=null) {
            handle.finish();
        }
    }

    private static void copy (String path, File sourceFolder, File destFolder) throws IOException {
        LOG.finest ("Copy " + path + " from " + sourceFolder + " to " + destFolder);
        File src = new File (sourceFolder, path);
        assert src.exists () : src + " exists.";
        src = FileUtil.normalizeFile (src);
        FileObject srcFO = FileUtil.toFileObject (src);

        File destFO = new File (destFolder, path);
        destFO.getParentFile ().mkdirs ();
        File dest = destFO.getParentFile ();
        dest = FileUtil.normalizeFile (dest);
        FileObject destFolderFO = FileUtil.toFileObject (dest);

        File destFile;
        if ((destFile = new File (dest, srcFO.getNameExt ())).exists ()) {
            if (! destFile.delete ()) {
                // if failed delete of the destFile => don't copy, otherwise will cause #159188
                return ;
            }
        }
        FileObject res = FileUtil.copyFile (srcFO, destFolderFO, srcFO.getName ());
        LOG.finest (srcFO + " was copied to " + destFolderFO + ". Result is: " + res);
    }

    private static Collection<String> getPluginFiles (File cluster, String cnb, File updateTracking) {
        Collection<String> res = new HashSet<String> ();
        LOG.log(Level.FINE, "Read update_tracking " + updateTracking + " file.");
        Node updateTrackingConf = getUpdateTrackingConf(updateTracking);
        if (updateTrackingConf == null) {
            return Collections.emptySet();
        }
        Set<String> moduleFiles = readModuleFiles(updateTrackingConf);
        String configFile = "config/Modules/" + cnb.replace ('.', '-') + ".xml"; // NOI18N

        moduleFiles.remove (configFile);

        for (String fileName : moduleFiles) {
            File file = new File (cluster, fileName);
            if (! file.exists ()) {
                LOG.log (Level.WARNING, "File " + file + " doesn't exist for module " + cnb);
                continue;
            }
            if (file.equals (updateTracking)) {
                continue;
            }
            res.add (fileName);
        }

        res.add (TRACKING_FILE_NAME + '/' + cnb.replace ('.', '-') + ".xml"); // NOI18N);

        LOG.log(Level.FINEST, cnb + " has files: " + res);
        return res;
    }

    private static File locateUpdateTracking (String cnb, File cluster) {
        String fileNameToFind = TRACKING_FILE_NAME + '/' + cnb.replace ('.', '-') + ".xml"; // NOI18N
        File ut = new File (cluster, fileNameToFind);
        if (ut.exists ()) {
            return ut;
        }
        throw new IllegalArgumentException (ut + " doesn't exist."); // NOI18N
    }

    private static Node getUpdateTrackingConf (File moduleUpdateTracking) {
        Document document = null;
        InputStream is;
        try {
            is = new BufferedInputStream (new FileInputStream (moduleUpdateTracking));
            InputSource xmlInputSource = new InputSource (is);
            document = XMLUtil.parse (xmlInputSource, false, false, null, org.openide.xml.EntityCatalog.getDefault ());
            if (is != null) {
                is.close ();
            }
        } catch (SAXException saxe) {
            LOG.log(Level.WARNING, "SAXException when reading " + moduleUpdateTracking + ", cause: " + saxe);
            //for issue #217118 investigation what is corrupted and how
            FileReader reader = null;
            try {
                reader = new FileReader(moduleUpdateTracking);
                char[] text = new char[1024];
                String fileContent = "";
                while (reader.read(text) > 0) {
                    fileContent += String.copyValueOf(text);
                }
                LOG.log(Level.WARNING, "SAXException in file:\n------FILE START------\n " + fileContent + "\n------FILE END-----\n");
            } catch (Exception ex) {
                //don't need to fail in logging
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException ex) {
                        //don't need any info from logging fail
                    }
                }
            }
            return null;
        } catch (IOException ioe) {
            LOG.log(Level.WARNING, null, ioe);
        }

        assert document.getDocumentElement () != null : "File " + moduleUpdateTracking + " must contain <module> element.";
        return getModuleElement (document.getDocumentElement ());
    }

    private static Node getModuleElement (Element element) {
        Node lastElement = null;
        assert ELEMENT_MODULE.equals (element.getTagName ()) : "The root element is: " + ELEMENT_MODULE + " but was: " + element.getTagName ();
        NodeList listModuleVersions = element.getElementsByTagName (ELEMENT_VERSION);
        for (int i = 0; i < listModuleVersions.getLength (); i++) {
            lastElement = getModuleLastVersion (listModuleVersions.item (i));
            if (lastElement != null) {
                break;
            }
        }
        return lastElement;
    }

    private static Node getModuleLastVersion (Node version) {
        Node attrLast = version.getAttributes ().getNamedItem (ATTR_LAST);
        assert attrLast != null : "ELEMENT_VERSION must contain ATTR_LAST attribute.";
        if (Boolean.valueOf (attrLast.getNodeValue ()).booleanValue ()) {
            return version;
        } else {
            return null;
        }
    }

    private static Set<String> readModuleFiles (Node version) {
        Set<String> files = new HashSet<String> ();
        NodeList fileNodes = version.getChildNodes ();
        for (int i = 0; i < fileNodes.getLength (); i++) {
            if (fileNodes.item (i).hasAttributes ()) {
                NamedNodeMap map = fileNodes.item (i).getAttributes ();
                files.add (map.getNamedItem (ATTR_FILE_NAME).getNodeValue ());
                LOG.log(Level.FINE,
                        "File for import: " +
                        map.getNamedItem(ATTR_FILE_NAME).getNodeValue());
            }
        }
        return files;
    }

    private static void refreshModuleList () {
        // XXX: the modules list should be refresh automatically when config/Modules/ changes
        final FileObject modulesRoot = FileUtil.getConfigFile(MODULES);
        LOG.log (Level.FINE,
                "It\'s a hack: Call refresh on " + modulesRoot +
                " file object.");
        if (modulesRoot != null) {
            try {
                FileUtil.runAtomicAction (new FileSystem.AtomicAction () {

                    @Override
                    public void run () throws IOException {
                        modulesRoot.getParent ().refresh ();
                        modulesRoot.refresh ();
                    }
                });
            } catch (IOException ex) {
                Exceptions.printStackTrace (ex);
            }
        }
    }

    public static void touchLastModified (File cluster) {
        try {
            File stamp = new File (cluster, LAST_MODIFIED);
            if (! stamp.createNewFile ()) {
                stamp.setLastModified (System.currentTimeMillis ());
                if (! stamp.setLastModified (System.currentTimeMillis ())) {
                    stamp.delete ();
                    stamp = new File (cluster, LAST_MODIFIED);
                    stamp.setLastModified (System.currentTimeMillis ());
                }
            }
        } catch (IOException ex) {
            LOG.log(Level.INFO, ex.getMessage(), ex);
        }
    }
    
    private static boolean isBlacklisted(UpdateElement el) {
        String blacklist = System.getProperty ("plugin.import.blacklist", ""); // NOI18N
        if (! blacklist.isEmpty()) {
            blacklist = blacklist + ','; // NOI18N
        }
        blacklist = blacklist + NbBundle.getMessage(PluginImporter.class, "plugin.import.blacklist"); // NOI18N
        LOG.fine("Blacklist: " + blacklist);
        StringTokenizer tokens = new StringTokenizer(blacklist, ",");
        while(tokens.hasMoreTokens()) {
            if (el.getCodeName().equals(tokens.nextToken())) {
                return true;
            }
        }
        return false;
    }
}
