package org.chromium.devtools.jsdoc.checks;

import com.google.javascript.jscomp.NodeUtil;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public final class DisallowedGlobalPropertiesChecker extends ContextTrackingChecker {
    private static final Set<String> GLOBAL_OBJECT_NAMES = new HashSet<>();
    private static final Set<String> DISALLOWED_PROPERTIES = new HashSet<>();
    static {
        GLOBAL_OBJECT_NAMES.add("window");
        GLOBAL_OBJECT_NAMES.add("self");
        DISALLOWED_PROPERTIES.add("document");
        DISALLOWED_PROPERTIES.add("addEventListener");
        DISALLOWED_PROPERTIES.add("removeEventListener");
        DISALLOWED_PROPERTIES.add("requestAnimationFrame");
        DISALLOWED_PROPERTIES.add("cancelAnimationFrame");
        DISALLOWED_PROPERTIES.add("getSelection");
    }

    private static final FunctionRecord TOP_LEVEL_FUNCTION = new FunctionRecord();

    private final Map<FunctionRecord, Set<String>> declaredLocalVariables = new HashMap<>();
    private final Map<FunctionRecord, List<Node>> globalPropertyAccessNodes = new HashMap<>();

    @Override
    protected void enterNode(Node node) {
        switch (node.getToken()) {
            case VAR:
                handleVar(node);
                break;
            case CONST:
                handleVar(node);
                break;
            case LET:
                handleVar(node);
                break;
            case NAME:
                handleName(node);
                break;
            case STRING:
                handleString(node);
                break;
            case FUNCTION:
            case SCRIPT:
                enterFunctionOrScript();
                break;
            default:
                break;
        }
    }

    @Override
    protected void leaveNode(Node node) {
        switch (node.getToken()) {
            case FUNCTION:
            case SCRIPT:
                leaveFunctionOrScript();
                break;
            default:
                break;
        }
    }

    private void enterFunctionOrScript() {
        FunctionRecord function = getCurrentFunction();
        declaredLocalVariables.put(function, new HashSet<String>());
        globalPropertyAccessNodes.put(function, new ArrayList<Node>());
    }

    private void leaveFunctionOrScript() {
        FunctionRecord function = getCurrentFunction();
        if (!function.suppressesGlobalPropertiesCheck()) {
            checkAccessNodes(globalPropertyAccessNodes.get(function));
        }
        declaredLocalVariables.remove(function);
        globalPropertyAccessNodes.remove(function);
    }

    private void checkAccessNodes(List<Node> nodes) {
        FunctionRecord function = getCurrentFunction();
        for (Node node : nodes) {
            String name = getContext().getNodeText(node);
            if (!functionHasVisibleIdentifier(function, name)) {
                reportErrorAtNodeStart(node,
                        String.format(
                                "Access to \"%s\" property of global object is disallowed", name));
            }
        }
    }

    private void handleVar(Node varNode) {
        Node nameNode = varNode.getFirstChild();
        if (nameNode == null) {
            return;
        }
        String name = nameNode.getString();
        if (name != null) {
            declaredLocalVariables.get(getCurrentFunction()).add(name);
        }
    }

    private void handleName(Node nameNode) {
        Node parent = nameNode.getParent();
        if (parent != null && parent.getToken() == Token.FUNCTION) {
            return;
        }

        String name = getContext().getNodeText(nameNode);
        if (!DISALLOWED_PROPERTIES.contains(name)) {
            return;
        }

        if (parent != null && parent.getToken() == Token.GETPROP) {
            boolean isGlobalPropertyAccess = parent.getFirstChild() == nameNode;
            if (!isGlobalPropertyAccess) {
                return;
            }
        }
        globalPropertyAccessNodes.get(getCurrentFunction()).add(nameNode);
    }

    private void handleString(Node stringNode) {
        String name = getContext().getNodeText(stringNode);
        if (!DISALLOWED_PROPERTIES.contains(name)) {
            return;
        }

        Node parent = stringNode.getParent();
        if (parent == null || parent.getToken() != Token.GETPROP) {
            return;
        }

        Node objectNode = parent.getFirstChild();
        boolean isGlobalObjectAccess = objectNode != null && isGlobalObject(objectNode)
                && objectNode.getNext() == stringNode;
        if (isGlobalObjectAccess) {
            globalPropertyAccessNodes.get(getCurrentFunction()).add(stringNode);
        }
    }

    private FunctionRecord getCurrentFunction() {
        FunctionRecord function = getState().getCurrentFunctionRecord();
        return function == null ? TOP_LEVEL_FUNCTION : function;
    }

    private boolean isGlobalObject(Node node) {
        String name = getContext().getNodeText(node);
        if (!GLOBAL_OBJECT_NAMES.contains(name)) {
            return false;
        }
        return node.getToken() == Token.NAME
                && !functionHasVisibleIdentifier(getCurrentFunction(), name);
    }

    private boolean functionHasVisibleIdentifier(FunctionRecord function, String name) {
        if (functionHasLocalIdentifier(function, name)) {
            return true;
        }
        if (function == TOP_LEVEL_FUNCTION) {
            return false;
        }
        FunctionRecord parent = function.enclosingFunctionRecord;
        return functionHasVisibleIdentifier(parent == null ? TOP_LEVEL_FUNCTION : parent, name);
    }

    private boolean functionHasLocalIdentifier(FunctionRecord function, String name) {
        return function.parameterNames.contains(name)
                || declaredLocalVariables.get(function).contains(name);
    }
}
