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 org.chromium.devtools.jsdoc.ValidationCheck;
import org.chromium.devtools.jsdoc.ValidatorContext;

import java.util.ArrayList;
import java.util.List;

public class ContextTrackingValidationCheck extends ValidationCheck {
    private ContextTrackingState state;
    private final List<ContextTrackingChecker> clients = new ArrayList<>(5);

    @Override
    protected void setContext(ValidatorContext context) {
        super.setContext(context);
        state = new ContextTrackingState(context);
        registerClient(new ProtoFollowsExtendsChecker());
        registerClient(new MethodAnnotationChecker());
        registerClient(new FunctionReceiverChecker());
        registerClient(new DisallowedGlobalPropertiesChecker());
    }

    @Override
    public void doVisit(Node node) {
        switch (node.getToken()) {
            case ASSIGN:
            case VAR:
                enterAssignOrVarNode(node);
                break;
            case FUNCTION:
                enterFunctionNode(node);
                break;
            default:
                break;
        }

        enterNode(node);
    }

    @Override
    public void didVisit(Node node) {
        leaveNode(node);

        switch (node.getToken()) {
            case ASSIGN:
                leaveAssignNode(node);
                break;
            case FUNCTION:
                leaveFunctionNode(node);
                break;
            default:
                break;
        }
    }

    public void registerClient(ContextTrackingChecker client) {
        this.clients.add(client);
        client.setState(state);
    }

    private void enterNode(Node node) {
        for (ContextTrackingChecker client : clients) {
            client.enterNode(node);
        }
    }

    private void leaveNode(Node node) {
        for (ContextTrackingChecker client : clients) {
            client.leaveNode(node);
        }
    }

    private void enterFunctionNode(Node node) {
        TypeRecord parentType =
                state.getCurrentFunctionRecord() == null ? state.getCurrentTypeRecord() : null;
        Node nameNode = AstUtil.getFunctionNameNode(node);
        String functionName = nameNode == null ? null : state.getNodeText(nameNode);
        FunctionRecord functionRecord = new FunctionRecord(node, functionName,
                getFunctionParameterNames(node), parentType, state.getCurrentFunctionRecord());
        state.pushFunctionRecord(functionRecord);
        rememberTypeRecordIfNeeded(functionName, functionRecord.info);
    }

    @SuppressWarnings("unused")
    private void leaveFunctionNode(Node node) {
        state.functionRecords.removeLast();
    }

    private void enterAssignOrVarNode(Node node) {
        String assignedTypeName = getAssignedTypeName(node);
        if (assignedTypeName == null) {
            return;
        }
        if (AstUtil.isPrototypeName(assignedTypeName)) {
            // MyType.prototype = ...
            String typeName = AstUtil.getTypeNameFromPrototype(assignedTypeName);
            TypeRecord typeRecord = state.typeRecordsByTypeName.get(typeName);
            // We should push anything here to maintain a valid current type record.
            state.pushTypeRecord(typeRecord);
            state.pushFunctionRecord(null);
            return;
        }
    }

    private void leaveAssignNode(Node assignment) {
        String assignedTypeName = getAssignedTypeName(assignment);
        if (assignedTypeName == null) {
            return;
        }
        if (AstUtil.isPrototypeName(assignedTypeName)) {
            // Remove the current type record when leaving prototype object.
            state.typeRecords.removeLast();
            state.functionRecords.removeLast();
            return;
        }
    }

    private String getAssignedTypeName(Node assignment) {
        Node node = AstUtil.getAssignedTypeNameNode(assignment);
        return getNodeText(node);
    }

    private List<String> getFunctionParameterNames(Node functionNode) {
        List<String> parameterNames = new ArrayList<String>();
        Node parametersNode = NodeUtil.getFunctionParameters(functionNode);
        for (int i = 0, childCount = parametersNode.getChildCount(); i < childCount; ++i) {
            Node paramNode = parametersNode.getChildAtIndex(i);
            String paramText = state.getContext().getNodeText(paramNode);

            // Handle rest parameters
            if ("...".equals(paramText)) continue;

            // Handle default parameters (ES6)
            String paramName = paramText.split("=")[0].trim();
            parameterNames.add(paramName);
        }
        return parameterNames;
    }

    private boolean rememberTypeRecordIfNeeded(String typeName, JSDocInfo info) {
        if (info == null) {
            return false;
        }
        if (typeName == null) {
            return info.isConstructor() || info.isInterface();
        }
        if (!info.isConstructor() && !info.isInterface()) {
            return false;
        }
        TypeRecord record = new TypeRecord(typeName, info);
        state.typeRecordsByTypeName.put(typeName, record);
        return true;
    }
}
