/*
 * 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.javascript.v8debug;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.lib.v8debug.V8Command;
import org.netbeans.lib.v8debug.V8Request;
import org.netbeans.lib.v8debug.V8Response;
import org.netbeans.lib.v8debug.V8Script;
import org.netbeans.lib.v8debug.commands.Scripts;
import org.netbeans.modules.javascript2.debug.sources.SourceContent;
import org.netbeans.modules.javascript2.debug.sources.SourceFilesCache;
import org.netbeans.modules.web.common.sourcemap.SourceMapsScanner;
import org.netbeans.modules.web.common.sourcemap.SourceMapsTranslator;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.NbBundle;

/**
 *
 * @author Martin Entlicher
 */
public class ScriptsHandler {
    
    private static final Logger LOG = Logger.getLogger(ScriptsHandler.class.getName());
    
    // The length of the node.js wrapper header: require('module').wrapper[0]
    private static final int DEFAULT_FIRST_LINE_COLUMN_SHIFT = 62;
    private static final boolean USE_SOURCE_MAPS =
            Boolean.parseBoolean(System.getProperty("javascript.debugger.useSourceMaps", "true"));


    private final Map<Long, V8Script> scriptsById = new HashMap<>();
    private final Map<URL, V8Script> scriptsByURL = new HashMap<>();
    private final Map<URL, Integer> scriptsFirstLineShifts = new HashMap<>();

    private final boolean doPathTranslation;
    private final int numPrefixes;
    @NullAllowed
    private final String[] localPathPrefixes;
    private final char localPathSeparator;
    @NullAllowed
    private final FileObject[] localRoots;
    @NullAllowed
    private final FileObject[] localPathExclusionFilters;
    @NullAllowed
    private final String[] serverPathPrefixes;
    private final char serverPathSeparator;
    private final String remotePathPrefix;
    private final V8Debugger dbg;
    private final SourceMapsTranslator smt;
    
    ScriptsHandler(@NullAllowed List<String> localPaths,
                   @NullAllowed List<String> serverPaths,
                   Collection<String> localPathExclusionFilters,
                   @NullAllowed V8Debugger dbg) {
        if (dbg != null) {
            this.remotePathPrefix = dbg.getHost()+"_"+dbg.getPort()+"/";
        } else {
            // dbg can be null in tests
            this.remotePathPrefix = "";
        }
        if (!localPaths.isEmpty() && !serverPaths.isEmpty()) {
            this.doPathTranslation = true;
            int n = localPaths.size();
            this.numPrefixes = n;
            this.localPathPrefixes = new String[n];
            this.serverPathPrefixes = new String[n];
            for (int i = 0; i < n; i++) {
                this.localPathPrefixes[i] = stripSeparator(localPaths.get(i));
            }
            this.localPathSeparator = findSeparator(localPaths.get(0));
            for (int i = 0; i < n; i++) {
                this.serverPathPrefixes[i] = stripSeparator(serverPaths.get(i));
            }
            this.serverPathSeparator = findSeparator(serverPaths.get(0));
        } else {
            this.doPathTranslation = false;
            this.localPathPrefixes = this.serverPathPrefixes = null;
            this.localPathSeparator = this.serverPathSeparator = 0;
            this.numPrefixes = 0;
        }
        if (!localPaths.isEmpty()) {
            FileObject[] lroots = new FileObject[localPaths.size()];
            int i = 0;
            for (String localPath : localPaths) {
                FileObject localRoot = FileUtil.toFileObject(FileUtil.normalizeFile(new File(localPath)));
                if (localRoot != null) {
                    lroots[i++] = localRoot;
                }
            }
            if (i < localPaths.size()) {
                lroots = Arrays.copyOf(lroots, i);
            }
            this.localRoots = lroots;
            if (USE_SOURCE_MAPS) {
                this.smt = SourceMapsScanner.getInstance().scan(this.localRoots);
            } else {
                this.smt = null;
            }
        } else {
            this.localRoots = null;
            if (USE_SOURCE_MAPS) {
                this.smt = SourceMapsTranslator.create();
            } else {
                this.smt = null;
            }
        }
        if (!localPathExclusionFilters.isEmpty()) {
            FileObject[] lpefs = new FileObject[localPathExclusionFilters.size()];
            int i = 0;
            for (String lpef : localPathExclusionFilters) {
                FileObject localRoot = FileUtil.toFileObject(new File(lpef));
                if (localRoot != null) {
                    lpefs[i++] = localRoot;
                } else {
                    lpefs = Arrays.copyOf(lpefs, lpefs.length - 1);
                }
            }
            this.localPathExclusionFilters = (lpefs.length > 0) ? lpefs : null;
        } else {
            this.localPathExclusionFilters = null;
        }
        LOG.log(Level.FINE,
                "ScriptsHandler: doPathTranslation = {0}, localPathPrefixes = {1}, separator = {2}, "+
                                "serverPathPrefixes = {3}, separator = {4}, "+
                                "localRoots = {5}, localPathExclusionFilters = {6}.",
                new Object[]{doPathTranslation, Arrays.toString(localPathPrefixes), localPathSeparator,
                             Arrays.toString(serverPathPrefixes), serverPathSeparator,
                             Arrays.toString(this.localRoots),
                             Arrays.toString(this.localPathExclusionFilters) });
        this.dbg = dbg;
    }

    void add(V8Script script) {
        synchronized (scriptsById) {
            scriptsById.put(script.getId(), script);
        }
    }
    
    void add(V8Script[] scripts) {
        synchronized (scriptsById) {
            for (V8Script script : scripts) {
                scriptsById.put(script.getId(), script);
            }
        }
    }
    
    void remove(long scriptId) {
        V8Script removed;
        synchronized (scriptsById) {
            removed = scriptsById.remove(scriptId);
        }
        if (removed != null) {
            URL removedURL = null;
            synchronized (scriptsByURL) {
                for (Map.Entry<URL, V8Script> entry : scriptsByURL.entrySet()) {
                    if (removed == entry.getValue()) {
                        removedURL = entry.getKey();
                        scriptsByURL.remove(removedURL);
                        break;
                    }
                }
            }
            if (removedURL != null) {
                synchronized (scriptsFirstLineShifts) {
                    scriptsFirstLineShifts.remove(removedURL);
                }
            }
        }
    }
    
    @CheckForNull
    public SourceMapsTranslator getSourceMapsTranslator() {
        return smt;
    }

    @CheckForNull
    public V8Script getScript(long id) {
        synchronized (scriptsById) {
            return scriptsById.get(id);
        }
    }
    
    @NonNull
    public Collection<V8Script> getScripts() {
        synchronized (scriptsById) {
            return new ArrayList<>(scriptsById.values());
        }
    }
    
    public boolean containsLocalFile(FileObject fo) {
        if (fo == null) {
            return false;
        }
        if (SourceFilesCache.URL_PROTOCOL.equals(fo.toURL().getProtocol())) {
            // virtual file created from source content
            return true;
        }
        if (localPathExclusionFilters != null) {
            for (FileObject lpef : localPathExclusionFilters) {
                if (FileUtil.isParentOf(lpef, fo)) {
                    return false;
                }
            }
        }
        if (localRoots == null) {
            return true;
        }
        for (FileObject localRoot : localRoots) {
            if (FileUtil.isParentOf(localRoot, fo)) {
                return true;
            }
        }
        return false;
    }
    
    public boolean containsRemoteFile(URL url) {
        if (!SourceFilesCache.URL_PROTOCOL.equals(url.getProtocol())) {
            return false;
        }
        String path;
        try {
            path = url.toURI().getPath();
        } catch (URISyntaxException usex) {
            return false;
        }

        int l = path.length();
        int index = 0;
        while (index < l && path.charAt(index) == '/') {
            index++;
        }
        int begin = path.indexOf('/', index);
        if (begin > 0) {
            // path.substring(begin + 1).startsWith(remotePathPrefix)
            return path.regionMatches(begin + 1, remotePathPrefix, 0, remotePathPrefix.length());
        } else {
            return false;
        }
    }
    
    @CheckForNull
    public FileObject getFile(long scriptId) {
        V8Script script = getScript(scriptId);
        if (script == null) {
            return null;
        } else {
            return getFile(script);
        }
    }
    
    @NonNull
    public FileObject getFile(@NonNull V8Script script) {
        String name = script.getName();
        if (name != null && script.getScriptType() == V8Script.Type.NORMAL) {
            File localFile = null;
            if (doPathTranslation) {
                try {
                    String lp = getLocalPath(name);
                    localFile = new File(lp);
                } catch (OutOfScope oos) {
                }
            } else {
                File f = new File(name);
                if (f.isAbsolute()) {
                    localFile = f;
                }
            }
            if (localFile != null) {
                FileObject fo = FileUtil.toFileObject(localFile);
                if (fo != null) {
                    synchronized (scriptsByURL) {
                        scriptsByURL.put(fo.toURL(), script);
                    }
                    return fo;
                }
            }
        }
        if (name == null) {
            name = "unknown.js";
        }
        // prepend <host>_<port>/ to the name.
        name = remotePathPrefix + name;
        String content = script.getSource();
        URL sourceURL;
        if (content != null) {
            sourceURL = SourceFilesCache.getDefault().getSourceFile(name, content.hashCode(), content);
        } else {
            sourceURL = SourceFilesCache.getDefault().getSourceFile(name, 1234, new ScriptContentLoader(script, dbg));
        }
        synchronized (scriptsByURL) {
            scriptsByURL.put(sourceURL, script);
        }
        return URLMapper.findFileObject(sourceURL);
    }
    
    /**
     * Find a known script by it's actual URL.
     * @param scriptURL Script's URL returned by {@link #getFile(org.netbeans.lib.v8debug.V8Script)}
     * @return the script or <code>null</code> when not found.
     */
    @CheckForNull
    public V8Script findScript(@NonNull URL scriptURL) {
        synchronized (scriptsByURL) {
            return scriptsByURL.get(scriptURL);
        }
    }
    
    /**
     * Get a shift of columns on the first line of the script.
     * The scripts can have prepended an extra code on the first line, which was
     * not part of the original file. This change affects source maps.
     * Be sure to consider this shift when interpreting source map translations.
     * @param fo The script's file source.
     * @return a non-negative shift of columns on the first line.
     */
    public int getScriptFirstLineColumnShift(FileObject fo) {
        URL url = fo.toURL();
        if (SourceFilesCache.URL_PROTOCOL.equals(url.getProtocol())) {
            // Not a local file
            return DEFAULT_FIRST_LINE_COLUMN_SHIFT;
        }
        Integer shift = null;
        synchronized (scriptsFirstLineShifts) {
            shift = scriptsFirstLineShifts.get(url);
        }
        if (shift == null) {
            V8Script script = findScript(url);
            if (script == null) {
                return DEFAULT_FIRST_LINE_COLUMN_SHIFT;
            }
            // The shift should not be larger than the source start:
            String ss = script.getSourceStart();
            String firstLine = null;
            try {
                List<String> lines = fo.asLines();
                Iterator<String> linesIterator = lines.iterator();
                if (linesIterator.hasNext()) {
                    firstLine = linesIterator.next();
                }
            } catch (IOException ex) {}
            if (firstLine == null) { // no lines
                shift = 0;
            } else {
                shift = findOffsetIn(ss, firstLine);
                if (shift < 0) {
                    String content = script.getSource();
                    if (content == null) {
                        try {
                            content = new ScriptContentLoader(script, dbg).getContent();
                        } catch (IOException ex) {}
                    }
                    if (content != null) {
                        shift = findOffsetIn(content, firstLine);
                    } else {
                        shift = DEFAULT_FIRST_LINE_COLUMN_SHIFT;
                    }
                }
            }
            synchronized (scriptsFirstLineShifts) {
                scriptsFirstLineShifts.put(url, shift);
            }
        }
        return shift;
    }
    
    private static int findOffsetIn(String container, String text) {
        // Restrict the container to the first line only:
        int nc = container.length();
        int nIndex = container.indexOf('\n');
        if (nIndex < 0) {
            nIndex = nc;
        }
        int rIndex = container.indexOf('\r');
        if (rIndex < 0) {
            rIndex = nc;
        }
        nc = Math.min(nIndex, rIndex);
        if (nc < container.length()) {
            container = container.substring(0, nc);
        }
        if (text.startsWith(container)) {
            return 0;
        }
        int nt = text.length();
        for (int ic = 0; ic < nc; ic++) {
            int it = 0;
            int ict = ic;
            for (; it < nt && ict < nc; it++, ict++) {
                char c = container.charAt(ict);
                char t = text.charAt(it);
                if (c != t) {
                    break;
                }
            }
            if (ict == nc) {
                return ic;
            }
        }
        return -1; // not found
    }
    
    @CheckForNull
    public String getServerPath(@NonNull FileObject fo) {
        String serverPath;
        File file = FileUtil.toFile(fo);
        if (file != null) {
            String localPath = file.getAbsolutePath();
            try {
                serverPath = getServerPath(localPath);
            } catch (ScriptsHandler.OutOfScope oos) {
                serverPath = null;
            }
        } else {
            URL url = fo.toURL();
            V8Script script = findScript(url);
            if (script != null) {
                serverPath = script.getName();
            } else if (SourceFilesCache.URL_PROTOCOL.equals(url.getProtocol())) {
                String path = fo.getPath();
                int begin = path.indexOf('/');
                if (begin > 0) {
                    path = path.substring(begin + 1);
                    // subtract <host>_<port>/ :
                    if (path.startsWith(remotePathPrefix)) {
                        serverPath = path.substring(remotePathPrefix.length());
                    } else {
                        serverPath = null;
                    }
                } else {
                    serverPath = null;
                }
            } else {
                serverPath = null;
            }
        }
        return serverPath;
    }
    
    @CheckForNull
    public String getServerPath(@NonNull URL url) {
        if (!SourceFilesCache.URL_PROTOCOL.equals(url.getProtocol())) {
            return null;
        }
        String path;
        try {
            path = url.toURI().getPath();
        } catch (URISyntaxException usex) {
            return null;
        }
        int l = path.length();
        int index = 0;
        while (index < l && path.charAt(index) == '/') {
            index++;
        }
        int begin = path.indexOf('/', index);
        if (begin > 0) {
            // path.substring(begin + 1).startsWith(remotePathPrefix)
            if (path.regionMatches(begin + 1, remotePathPrefix, 0, remotePathPrefix.length())) {
                path = path.substring(begin + 1 + remotePathPrefix.length());
                return path;
            } else {
                // Path with a different prefix
                return null;
            }
        } else {
            return null;
        }
    }
    
    public String getLocalPath(@NonNull String serverPath) throws OutOfScope {
        if (!doPathTranslation) {
            return serverPath;
        } else {
            for (int i = 0; i < numPrefixes; i++) {
                if (isChildOf(serverPathPrefixes[i], serverPath)) {
                    return translate(serverPath, serverPathPrefixes[i], serverPathSeparator,
                                     localPathPrefixes[i], localPathSeparator);
                }
            }
        }
        throw new OutOfScope(serverPath, Arrays.toString(serverPathPrefixes));
    }
    
    public String getServerPath(@NonNull String localPath) throws OutOfScope {
        if (!doPathTranslation) {
            return localPath;
        } else {
            for (int i = 0; i < numPrefixes; i++) {
                if (isChildOf(localPathPrefixes[i], localPath)) {
                    return translate(localPath, localPathPrefixes[i], localPathSeparator,
                                     serverPathPrefixes[i], serverPathSeparator);
                }
            }
        }
        throw new OutOfScope(localPath, Arrays.toString(localPathPrefixes));
    }
    
    public File[] getLocalRoots() {
        if (localRoots == null) {
            return new File[]{};
        }
        int l = localRoots.length;
        File[] roots = new File[l];
        for (int i = 0; i < l; i++) {
            roots[i] = FileUtil.toFile(localRoots[i]);
        }
        return roots;
    }
    
    private static boolean isChildOf(String parent, String child) {
        if (!child.startsWith(parent)) {
            return false;
        }
        int l = parent.length();
        if (!isRootPath(parent)) { // When the parent is the root, do not do further checks.
            if (child.length() > l && !isSeparator(child.charAt(l))) {
                return false;
            }
        }
        return true;
    }
    
    private static String translate(String path, String pathPrefix, char pathSeparator, String otherPathPrefix, char otherPathSeparator) throws OutOfScope {
        if (!path.startsWith(pathPrefix)) {
            throw new OutOfScope(path, pathPrefix);
        }
        int l = pathPrefix.length();
        if (!isRootPath(pathPrefix)) { // When the prefix is the root, do not do further checks.
            if (path.length() > l && !isSeparator(path.charAt(l))) {
                throw new OutOfScope(path, pathPrefix);
            }
        }
        while (path.length() > l && isSeparator(path.charAt(l))) {
            l++;
        }
        String otherPath = path.substring(l);
        if (pathSeparator != otherPathSeparator) {
            otherPath = otherPath.replace(pathSeparator, otherPathSeparator);
        }
        if (otherPath.isEmpty()) {
            return otherPathPrefix;
        } else {
            if (isRootPath(otherPathPrefix)) { // Do not append further slashes to the root
                return otherPathPrefix + otherPath;
            } else {
                return otherPathPrefix + otherPathSeparator + otherPath;
            }
        }
    }
    
    private static char findSeparator(String path) {
        if (path.indexOf('/') >= 0) {
            return '/';
        }
        if (path.indexOf('\\') >= 0) {
            return '\\';
        }
        return '/';
    }

    private static boolean isSeparator(char c) {
        return c == '/' || c == '\\';
    }
    
    private static String stripSeparator(String path) {
        if (isRootPath(path)) { // Do not remove slashes the root
            return path;
        }
        while (path.length() > 1 && (path.endsWith("/") || path.endsWith("\\"))) {
            path = path.substring(0, path.length() - 1);
        }
        return path;
    }
    
    private static boolean isRootPath(String path) {
        if ("/".equals(path)) {
            return true;
        }
        if (path.length() == 4 && path.endsWith(":\\\\")) { // "C:\\"
            return true;
        }
        return false;
    }

    public static final class OutOfScope extends Exception {
        
        private OutOfScope(String path, String scope) {
            super(path);
        }
    }
    
    private static final class ScriptContentLoader implements SourceContent,
                                                              V8Debugger.CommandResponseCallback {
        
        private final V8Script script;
        private final V8Debugger dbg;
        private String content;
        private final Object contentLock = new Object();
        private String contentLoadError;
        
        public ScriptContentLoader(V8Script script, V8Debugger dbg) {
            this.script = script;
            this.dbg = dbg;
        }

        @NbBundle.Messages({ "ERR_NoSourceRequest=No source request has been sent.",
                             "ERR_Interrupted=Interrupted" })
        @Override
        public String getContent() throws IOException {
            if (content != null) {
                return content;
            }
            V8Script.Type st = script.getScriptType();
            V8Script.Types types = new V8Script.Types(st.NATIVE == st, st.EXTENSION == st, st.NORMAL == st);
            Scripts.Arguments sa = new Scripts.Arguments(types, new long[] { script.getId() },
                                                         true, null);
            V8Request request = dbg.sendCommandRequest(V8Command.Scripts, sa, this);
            if (request == null) {
                throw new IOException(Bundle.ERR_NoSourceRequest());
            }
            synchronized (contentLock) {
                if (content == null && contentLoadError == null) {
                    try {
                        contentLock.wait();
                    } catch (InterruptedException iex) {
                        throw new IOException(Bundle.ERR_Interrupted(), iex);
                    }
                }
                if (contentLoadError != null) {
                    throw new IOException(contentLoadError);
                } else {
                    return content;
                }
            }
        }

        @Override
        public long getLength() {
            return script.getSourceLength().getValue();
        }

        @NbBundle.Messages({ "ERR_ScriptFailedToLoad=The script failed to load.",
                             "ERR_ScriptHasNoSource=The script has no source." })
        @Override
        public void notifyResponse(V8Request request, V8Response response) {
            V8Script[] scripts;
            if (response != null) {
                Scripts.ResponseBody srb = (Scripts.ResponseBody) response.getBody();
                scripts = srb.getScripts();
            } else {
                scripts = null;
            }
            synchronized (contentLock) {
                if (scripts == null || scripts.length == 0) {
                    contentLoadError = Bundle.ERR_ScriptFailedToLoad();
                } else {
                    String source = scripts[0].getSource();
                    if (source == null) {
                        contentLoadError = Bundle.ERR_ScriptHasNoSource();
                    } else {
                        content = source;
                    }
                }
                contentLock.notifyAll();
            }
        }
    }

}
