/*
 * 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.ide.ergonomics.ant;

import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.filters.BaseFilterReader;
import org.apache.tools.ant.filters.ChainableReader;
import org.apache.tools.ant.taskdefs.Concat;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.FilterChain;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.StringResource;
import org.apache.tools.ant.types.resources.ZipResource;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.zip.ZipEntry;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/** Extracts icons and bundles from layer.
 *
 * @author Jaroslav Tulach <jtulach@netbeans.org>
 */
public final class ExtractLayer extends Task
implements FileNameMapper, URIResolver, EntityResolver {
    private List<FileSet> moduleSet = new ArrayList<FileSet>();
    public void addConfiguredModules(FileSet fs) {
        moduleSet.add(fs);
    }
    private List<FileSet> entries = new ArrayList<FileSet>();
    public void addConfiguredEntries(FileSet fs) {
        entries.add(fs);
    }

    private File output;
    public void setDestDir(File f) {
        output = f;
    }
    private File bundle;
    public void setBundle(File f) {
        bundle = f;
    }
    private String clusterName;
    public void setClusterName(String n) {
        clusterName = n;
    }
    private FilterChain bundleFilter;
    public void addConfiguredBundleFilter(FilterChain b) {
        bundleFilter = b;
    }

    private File badgeFile;
    public void setBadgeIcon(File f) {
        badgeFile = f;
    }

    @Override
    public void execute() throws BuildException {
        if (moduleSet.isEmpty()) {
            throw new BuildException();
        }
        if (output == null) {
            throw new BuildException();
        }
        if (clusterName == null) {
            throw new BuildException();
        }
        BufferedImage badgeIcon;
        try {
            badgeIcon = badgeFile == null ? ImageIO.read(ExtractLayer.class.getResourceAsStream("badge.png")) : ImageIO.read(badgeFile);
        } catch (IOException ex) {
            throw new BuildException("Error reading " + badgeFile, ex);
        }

        Transformer ft;
        Transformer rt;
        Transformer et;
        Transformer bt;


        try {
            StreamSource fullpaths;
            StreamSource relative;
            StreamSource entryPoints;
            StreamSource bundleEntryPoints;
            URL fu = ExtractLayer.class.getResource("full-paths.xsl");
            URL ru = ExtractLayer.class.getResource("relative-refs.xsl");
            URL eu = ExtractLayer.class.getResource("entry-points.xsl");
            URL bu = ExtractLayer.class.getResource("entry-points-to-bundle.xsl");
            fullpaths = new StreamSource(fu.openStream());
            relative = new StreamSource(ru.openStream());
            entryPoints = new StreamSource(eu.openStream());
            bundleEntryPoints = new StreamSource(bu.openStream());

            SAXTransformerFactory fack;
            fack = (SAXTransformerFactory)TransformerFactory.newInstance();
            assert Boolean.TRUE.equals(fack.getFeature(SAXTransformerFactory.FEATURE));
            fack.setURIResolver(this);

            ft = fack.newTransformer(fullpaths);
            rt = fack.newTransformer(relative);
            rt.setParameter("cluster.name", clusterName);
            et = fack.newTransformer(entryPoints);
            et.setParameter("cluster.name", clusterName);
            bt = fack.newTransformer(bundleEntryPoints);
        } catch (Exception ex) {
            throw new BuildException(ex);
        }

        StringBuilder modules = new StringBuilder();
        String sep = "\n    ";
        ByteArrayOutputStream uberLayer = new ByteArrayOutputStream();
        try {
            uberLayer.write("<?xml version='1.0' encoding='UTF-8'?>\n".getBytes("UTF-8"));
            uberLayer.write("<filesystem>\n".getBytes("UTF-8"));
        } catch (IOException iOException) {
            throw new BuildException(iOException);
        }
        ByteArrayOutputStream bundleHeader = new ByteArrayOutputStream();
        StreamResult bundleOut = new StreamResult(bundleHeader);
        StreamResult uberOut = new StreamResult(uberLayer);
        SAXParserFactory f = SAXParserFactory.newInstance();
        f.setValidating(false);
        f.setNamespaceAware(false);
        for (FileSet fs : moduleSet) {
            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            File basedir = ds.getBasedir();
            for (String path : ds.getIncludedFiles()) {
                File jar = new File(basedir, path);
                try {
                    JarFile jf = new JarFile(jar);
                    try {
                        Manifest mf = jf.getManifest();
                        if (mf == null) {
                            continue;
                        }
                        String modname = mf.getMainAttributes().getValue("OpenIDE-Module");
                        if (modname == null) {
                            continue;
                        }
                        String skip = mf.getMainAttributes().getValue("FeaturesOnDemand-Proxy-Layer");
                        if ("false".equals(skip)) {
                            continue;
                        }
                        String show = mf.getMainAttributes().getValue("AutoUpdate-Show-In-Client");
                        String base = modname.replaceFirst("/[0-9]+$", "");
                        if (!"false".equals(show)) {
                            modules.append(sep).append(base);
                            sep = ",\\\n    ";
                        }

                        String mflayer = mf.getMainAttributes().getValue("OpenIDE-Module-Layer");
                        if (mflayer != null) {
                            String n = mflayer.replaceFirst("/[^/]+$", "").replace('/', '.') + ".xml";
                            et.setParameter("filename", n);
                            et.transform(createSource(jf, jf.getEntry(mflayer)), uberOut);
                            bt.transform(createSource(jf, jf.getEntry(mflayer)), bundleOut);
                        }
                        java.util.zip.ZipEntry generatedLayer = jf.getEntry("META-INF/generated-layer.xml");
                        if (generatedLayer != null) {
                            et.setParameter("filename", base + "-generated.xml");
                            et.transform(createSource(jf, generatedLayer), uberOut);
                            bt.transform(createSource(jf, generatedLayer), bundleOut);
                        }

                    } finally {
                        jf.close();
                    }
                } catch (Exception x) {
                    throw new BuildException("Reading " + jar + ": " + x, x, getLocation());
                }
            }
        }

        Pattern concatPattern;
        Pattern copyPattern;
        String uberText = null;
        byte[] uberArr = null;
        DuplKeys duplKeys = null;
        try {
            uberLayer.write("</filesystem>\n".getBytes("UTF-8"));
            uberText = uberLayer.toString("UTF-8");
            uberArr = uberLayer.toByteArray();
            log("uberLayer for " + clusterName + "\n" + uberText, Project.MSG_VERBOSE);
            
            Set<String> concatregs = new TreeSet<String>();
            Set<String> copyregs = new TreeSet<String>();
            Map<String,String> keys = new TreeMap<String,String>();
            parse(new ByteArrayInputStream(uberArr), concatregs, copyregs, keys);

            log("Concats: " + concatregs, Project.MSG_VERBOSE);
            log("Copies : " + copyregs, Project.MSG_VERBOSE);

            StringBuilder sb = new StringBuilder();
            sep = "";
            for (String s : concatregs) {
                sb.append(sep);
                sb.append(s);
                sep = "|";
            }
            concatPattern = Pattern.compile(sb.toString());

            sb = new StringBuilder();
            sep = "";
            for (String s : copyregs) {
                sb.append(sep);
                sb.append(s);
                sep = "|";
            }
            copyPattern = Pattern.compile(sb.toString());

            duplKeys = new DuplKeys(keys.keySet());
        } catch (Exception ex) {
            throw new BuildException("Cannot parse layers: " + ex.getMessage(), ex);
        }
        Map<String,ResArray> bundles = new HashMap<String,ResArray>();
        bundles.put("", new ResArray());
        ResArray icons = new ResArray();

        for (FileSet fs : entries == null ? moduleSet : entries) {
            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            File basedir = ds.getBasedir();
            for (String path : ds.getIncludedFiles()) {
                File jar = new File(basedir, path);
                try {
                    JarFile jf = new JarFile(jar);
                    try {
                        Enumeration<JarEntry> en = jf.entries();
                        while (en.hasMoreElements()) {
                            JarEntry je = en.nextElement();
                            if (concatPattern.matcher(je.getName()).matches()) {
                                ZipEntry zipEntry = new ZipEntry(je);
                                String noExt = je.getName().replaceFirst("\\.[^\\.]*$", "");
                                int index = noExt.indexOf("_");
                                String suffix = index == -1 ? "" : noExt.substring(index + 1);
                                ResArray ra = bundles.get(suffix);
                                if (ra == null) {
                                    ra = new ResArray();
                                    bundles.put(suffix, ra);
                                }
                                ra.add(new ZipResource(jar, "UTF-8", zipEntry));
                                ra.add(new StringResource("\n\n"));
                            }
                            if (copyPattern.matcher(je.getName()).matches()) {
                                ZipEntry zipEntry = new ZipEntry(je);
                                Resource zr = new ZipResource(jar, "UTF-8", zipEntry);
                                if (badgeIcon != null) {
                                    icons.add(new IconResource(zr, badgeIcon));
                                } else {
                                    icons.add(zr);
                                }
                            }
                        }
                    } finally {
                        jf.close();
                    }
                } catch (Exception x) {
                    throw new BuildException("Reading " + jar + ": " + x, x, getLocation());
                }
            }
        }

        for (Map.Entry<String, ResArray> entry : bundles.entrySet()) {
            ResArray ra = entry.getValue();
            
            Concat concat = new Concat();
            concat.setProject(getProject());
            ra.add(new StringResource(""));
            concat.add(ra);
            concat.setDestfile(localeVariant(bundle, entry.getKey()));
            {
                FilterChain ch = new FilterChain();
                ch.add(duplKeys);
                concat.addFilterChain(ch);
                concat.addFilterChain(bundleFilter);
            }
            Concat.TextElement te = new Concat.TextElement();
            te.setProject(getProject());
            te.addText("\n\n\ncnbs=\\" + modules + "\n\n");
            te.setFiltering(false);
            try {
                final String antProjects = new String(bundleHeader.toByteArray(), "UTF-8");
                te.addText(antProjects + "\n\n");
            } catch (UnsupportedEncodingException ex) {
                throw new BuildException(ex);
            }
            concat.addFooter(te);
            concat.execute();
        }

        {
            HashMap<String,Resource> names = new HashMap<String,Resource>();
            HashSet<String> duplicates = new HashSet<String>();
            for (Resource r : icons) {
                String name = r.getName();
                Resource prev = names.put(name, r);
                if (prev != null) {
                    if (prev.getName().equals(r.getName())) {
                        continue;
                    }
                    duplicates.add(r.getName());
                    duplicates.add(prev.getName());
                }
            }
            if (!duplicates.isEmpty()) {
                throw new BuildException("Duplicated resources are forbidden: " + duplicates.toString().replace(',', '\n'));
            }
        }

        Copy copy = new Copy();
        copy.setProject(getProject());
        copy.add(icons);
        copy.setTodir(output);
        copy.add(this);
        copy.execute();

        try {
            StreamSource orig = new StreamSource(new ByteArrayInputStream(uberArr));
            DOMResult tmpRes = new DOMResult();
            ft.transform(orig, tmpRes);

            Node filesystem = tmpRes.getNode().getFirstChild();
            String n = filesystem.getNodeName();
            assert n.equals("filesystem") : n;
            if (filesystem.getChildNodes().getLength() > 0) {
                DOMSource tmpSrc = new DOMSource(tmpRes.getNode());
                StreamResult gen = new StreamResult(new File(output, "layer.xml"));
                rt.transform(tmpSrc, gen);
            }
        } catch (Exception ex) {
            throw new BuildException(ex);
        }
    }


    private void parse(
        final InputStream is,
        final Set<String> concat, final Set<String> copy,
        final Map<String,String> additionalKeys
    ) throws Exception {
        SAXParserFactory f = SAXParserFactory.newInstance();
        f.setValidating(false);
        f.setNamespaceAware(false);
        f.newSAXParser().parse(is, new DefaultHandler() {
            String prefix = "";
            @Override
            public void startElement(String uri, String localName, String qName,  Attributes attributes) throws SAXException {
                if (qName.equals("folder")) {
                    String n = attributes.getValue("name");
                    prefix += n + "/";
                } else if (qName.equals("file")) {
                    String n = attributes.getValue("name");
                    addResource(attributes.getValue("url"), true);
                    prefix += n;
                } else if (qName.equals("attr")) {
                    String name = attributes.getValue("name");
                    if (name.equals("SystemFileSystem.localizingBundle")) {
                        String bundlepath = attributes.getValue("stringvalue").replace('.', '/') + ".*properties";
                        concat.add(bundlepath);
			String key;
                        if (prefix.endsWith("/")) {
			    key = prefix.substring(0, prefix.length() - 1);
                        } else {
                            key = prefix;
                        }
			additionalKeys.put(key, bundlepath);
                    } else if (name.equals("iconResource") || name.equals("iconBase")) {
                        String s = attributes.getValue("stringvalue");
                        if (s == null) {
                            throw new BuildException("No stringvalue attribute for " + name);
                        }
                        addResource("nbresloc:" + s, false);
                    } else if (attributes.getValue("bundlevalue") != null) {
                        String bundlevalue = attributes.getValue("bundlevalue");
                        int idx = bundlevalue.indexOf('#');
                        String bundle = bundlevalue.substring(0, idx);
                        String key = bundlevalue.substring(idx + 1);
                        String bundlepath = bundle.replace('.', '/') + ".*properties";

			String prev = additionalKeys.put(key, bundle);

                        if (prev != null && !bundle.equals(prev)) {
                            throw new IllegalStateException("key " + key + " from " + bundlepath + " was already defined among " + prev);
                        }
                        concat.add(bundlepath);
                    } else {
                        addResource(attributes.getValue("urlvalue"), false);
                    }
                }
            }
            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {
                if (qName.equals("folder")) {
                    prefix = prefix.replaceFirst("[^/]+/$", "");
                } else if (qName.equals("file")) {
                    prefix = prefix.replaceFirst("[^/]+$", "");
                }
            }
            @Override
            public InputSource resolveEntity(String pub, String sys) throws IOException, SAXException {
                return new InputSource(new StringReader(""));
            }

            private void addResource(String url, boolean localAllowed) throws BuildException {
                if (url == null) {
                    return;
                }
                if (url.startsWith("nbres:")) {
                    url = "nbresloc:" + url.substring(6);
                }
                final String prfx = "nbresloc:";
                if (!url.startsWith(prfx)) {
                    if (localAllowed) {
                        if (url.startsWith("/")) {
                            copy.add(url.substring(1));
                        } else {
                            copy.add(".*/" + url);
                        }
                        return;
                    } else {
                        throw new BuildException("Unknown urlvalue was: " + url);
                    }
                } else {
                    url = url.substring(prfx.length());
                    if (url.startsWith("/")) {
                        url = url.substring(1);
                    }
                }
                url = url.replaceFirst("(\\.[^\\.])+$*", ".*$1");
                copy.add(url);
            }
        });
    }

    private static File localeVariant(File base, String locale) {
        if (locale.length() == 0) {
            return base;
        }
        String name = base.getName().replaceFirst("\\.", "_" + locale + ".");
        return new File(base.getParentFile(), name);
    }

    public void setFrom(String arg0) {
    }

    public void setTo(String arg0) {
    }

    /** Dash instead of slash file mapper */
    public String[] mapFileName(String fileName) {
        return new String[] { fileName.replace('/', '-') };
    }

    public Source resolve(String href, String base) throws TransformerException {
        return null;
    }

    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        return new InputSource(new ByteArrayInputStream(new byte[0]));
    }

    private Source createSource(JarFile jf, java.util.zip.ZipEntry entry)  {
        try {
            DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
            f.setValidating(false);
            DocumentBuilder b = f.newDocumentBuilder();
            b.setEntityResolver(this);
            Document doc = b.parse(jf.getInputStream(entry));
            return new DOMSource(doc);
        } catch (Exception ex) {
            throw new BuildException(ex);
        }
    }

    private static final class ResArray extends ArrayList<Resource>
    implements ResourceCollection {
        public boolean isFilesystemOnly() {
            return false;
        }
    }

    private class DuplKeys extends BaseFilterReader
    implements ChainableReader {
        private final Set<String> acceptKeys;
        private Map<String,String> map;
        private String line;
        private int lineIdx;
        
        public DuplKeys(Set<String> acceptKeys) {
            this.acceptKeys = acceptKeys;
        }

        public DuplKeys(Reader in, Set<String> acceptKeys) {
            super(new BufferedReader(in));
            this.acceptKeys = acceptKeys;
        }

        @Override
        public Reader chain(Reader rdr) {
            return new DuplKeys(rdr, acceptKeys);
        }
        
        private BufferedReader in() {
           return (BufferedReader) in;
        }

        @Override
        public int read() throws IOException {
            int equals;
            String key;
            
            for (;;) {
                if (line != null) {
                    final int len = line.length();
                    if (lineIdx < len) {
                        return line.charAt(lineIdx++);
                    } else {
                        if (len > 0 && line.charAt(len - 1)  == '\\') {
                            line = in().readLine();
                            lineIdx = 0;
                        } else {
                            line = null;
                        }
                        return '\n';
                    }
                }
                do { 
                    line = in().readLine();
                    if (line == null) {
                        return -1;
                    }
                } while (line.startsWith("#"));
                lineIdx = 0;

                equals = line.indexOf('=');
                if (equals == -1) {
                    line = null;
                    continue;
                }
                key = line.substring(0, equals).trim();
                if (!acceptKeys.contains(key)) {
                    line = null;
                    continue;
                }
                final String value = line.substring(equals + 1);
                if (map == null) {
                    map = new HashMap<String, String>();
                }
                if (map.containsKey(key)) {
                    final String oldValue = map.get(key);
                    if (!value.equals(oldValue)) {
                        final String msg = "The key " + key + 
                            " is duplicated and values are not identical: '" + 
                            value + "' and '" + oldValue + "'!";
                        throw new BuildException(msg);
                    }
                    // ignore the line
                    line = null;
                    continue;
                }
                map.put(key, value);
                continue;
            }
        }
        
        
    }
}
