/*
 * 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.core.osgi;

import java.beans.PropertyVetoException;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.filesystems.FileStatusListener;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.LocalFileSystem;
import org.openide.filesystems.MultiFileSystem;
import org.openide.filesystems.Repository;
import org.openide.filesystems.XMLFileSystem;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.NbCollections;
import org.osgi.framework.Bundle;
import org.xml.sax.SAXException;

/**
 * Default repository to which layers can be added or removed.
 */
class OSGiRepository extends Repository {

    private static final Logger LOG = Logger.getLogger(OSGiRepository.class.getName());
    public static final OSGiRepository DEFAULT = new OSGiRepository();

    private final SFS fs;

    private OSGiRepository() {
        this(new SFS());
    }

    private OSGiRepository(SFS fs) {
        super(fs);
        this.fs = fs;
    }

    private static URL[] layersFor(List<Bundle> bundles) {
        List<URL> layers = new ArrayList<URL>(2);
        for (Bundle b : bundles) {
            if (b.getSymbolicName().equals("org.netbeans.modules.autoupdate.ui")) { // NOI18N
                // Won't work anyway, so don't even try.
                continue;
            }
            String explicit = b.getHeaders().get("OpenIDE-Module-Layer");
            if (explicit != null) {
                String base, ext;
                int idx = explicit.lastIndexOf('.'); // NOI18N
                if (idx == -1) {
                    base = explicit;
                    ext = ""; // NOI18N
                } else {
                    base = explicit.substring(0, idx);
                    ext = explicit.substring(idx);
                }
                for (String suffix : NbCollections.iterable(NbBundle.getLocalizingSuffixes())) {
                    URL layer = b.getResource(base + suffix + ext);
                    if (layer != null) {
                        layers.add(layer);
                    } else if (suffix.isEmpty()) {
                        LOG.log(Level.WARNING, "no such layer {0} in {1} of state {2}", new Object[] {explicit, b.getSymbolicName(), b.getState()});
                    }
                }
            }
            URL generated = b.getResource("META-INF/generated-layer.xml");
            if (generated != null) {
                layers.add(generated);
            }
        }
        return layers.toArray(new URL[layers.size()]);
    }

    public void addLayersFor(List<Bundle> bundles) {
        URL[] resources = layersFor(bundles);
        if (resources.length > 0) {
//            System.err.println("adding layers: " + Arrays.toString(resources));
            fs.addLayers(resources);
        }
    }

    public void removeLayersFor(List<Bundle> bundles) {
        URL[] resources = layersFor(bundles);
        if (resources.length > 0) {
//            System.err.println("removing layers: " + Arrays.toString(resources));
            fs.removeLayers(resources);
        }
    }

    private static final class SFS extends MultiFileSystem implements LookupListener {

        static {
            Object _3 = FileStatusListener.class;
            Object _4 = LookupEvent.class; // FELIX-3477
        }

        private static final class Layers extends MultiFileSystem {
            Layers() {
                setPropagateMasks(true);
            }
            void _setDelegates(Collection<FileSystem> delegates) {
                setDelegates(delegates.toArray(new FileSystem[delegates.size()]));
            }
        }

        private final Map<String,FileSystem> fss = new HashMap<String,FileSystem>();
        private final FileSystem userdir;
        private final Layers layers;
        private final Lookup.Result<FileSystem> dynamic = Lookup.getDefault().lookupResult(FileSystem.class);

        @SuppressWarnings({"LeakingThisInConstructor", "deprecation"})
        SFS() {
            dynamic.addLookupListener(this);
            layers = new Layers();
            File config = null;
            String netbeansUser = System.getProperty("netbeans.user");
            if (netbeansUser != null) {
                config = new File(netbeansUser, "config");
            }
            if (config != null && (config.isDirectory() || config.mkdirs())) {
                LocalFileSystem lfs = new LocalFileSystem();
                try {
                    lfs.setRootDirectory(config);
                } catch (Exception x) {
                    LOG.log(Level.WARNING, "Could not set userdir: " + config, x);
                }
                userdir = lfs;
            } else {
                // no persisted configuration
                userdir = FileUtil.createMemoryFileSystem();
            }
            resetAll();
            try {
                setSystemName("SystemFileSystem");
            } catch (PropertyVetoException x) {
                throw new AssertionError(x);
            }
        }

        private synchronized void addLayers(URL... resources) {
            LOG.log(Level.FINE, "addLayers: {0}", Arrays.asList(resources));
            for (URL resource : resources) {
                try {
                    fss.put(resource.toString(), new XMLFileSystem(resource));
                } catch (SAXException x) {
                    LOG.log(Level.WARNING, "Could not parse layer: " + resource, x);
                }
            }
            resetLayers();
        }

        private synchronized void removeLayers(URL... resources) {
            for (URL resource : resources) {
                fss.remove(resource.toString());
            }
            resetLayers();
        }

        private void resetLayers() {
            layers._setDelegates(fss.values());
        }

        private void resetAll() {
            List<FileSystem> delegates = new ArrayList<FileSystem>();
            delegates.add(userdir);
            Collection<? extends FileSystem> dyn = dynamic.allInstances();
            LOG.log(Level.FINE, "dyn={0}", dyn);
            for (FileSystem fs : dyn) {
                if (Boolean.TRUE.equals(fs.getRoot().getAttribute("fallback"))) { // NOI18N
                    continue;
                }
                delegates.add(fs);
            }
            delegates.add(layers);
            for (FileSystem fs : dyn) {
                if (Boolean.TRUE.equals(fs.getRoot().getAttribute("fallback"))) { // NOI18N
                    delegates.add(fs);
                }
            }
            setDelegates(delegates.toArray(new FileSystem[delegates.size()]));
            assert getRoot().isValid();
            assert !isReadOnly() : delegates;
        }

        public @Override void resultChanged(LookupEvent ev) {
            resetAll();
        }

    }

}
