package com.chrisfolger.needsmoredojo.refactoring;

import com.intellij.lang.ASTNode;
import com.intellij.lang.javascript.psi.*;
import com.intellij.lang.javascript.psi.impl.JSChangeUtil;
import com.intellij.lang.javascript.psi.util.JSUtils;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.psi.PsiElement;

public class UtilConverter implements DeclareFinder.CompletionCallback
{
    @Override
    public void run(Object[] result)
    {
        JSCallExpression expression = (JSCallExpression) result[0];
        final JSReturnStatement returnStatement = (JSReturnStatement) result[1];

        // this will be used to determine what we mixin to the util
        JSArrayLiteralExpression arrayLiteral = (JSArrayLiteralExpression) expression.getArguments()[0];
        final JSExpression[] expressionsToMixin = arrayLiteral.getExpressions();

        // now we need to get the object literal with all of the function names
        JSObjectLiteralExpression literal = (JSObjectLiteralExpression) expression.getArguments()[1];
        final JSProperty[] methodsToConvert = literal.getProperties();

        CommandProcessor.getInstance().executeCommand(expression.getProject(), new Runnable() {
            @Override
            public void run() {
                ApplicationManager.getApplication().runWriteAction(new Runnable() {
                    @Override
                    public void run() {
                        doRefactor(returnStatement, expressionsToMixin, methodsToConvert);
                    }
                });
            }
        },
        "Convert module to use Util Pattern",
        "Convert module to use Util Pattern");
    }

    public void doRefactor(JSReturnStatement originalReturnStatement, JSExpression[] mixins, JSProperty[] properties) {
        // insert new items before this
        PsiElement parent = originalReturnStatement.getParent();

        StringBuilder mixinArray = new StringBuilder();
        for (JSExpression mixin : mixins) {
            if (mixinArray.toString().equals("")) {
                mixinArray.append(mixin.getText());
            } else {
                mixinArray.append(", " + mixin.getText());
            }
        }
        String declareStatement = String.format("var util = declare([%s], {});", mixinArray.toString());
        ASTNode node = JSChangeUtil.createStatementFromText(parent.getProject(), declareStatement, JSUtils.getDialect(parent.getContainingFile()));
        parent.addBefore(node.getPsi(), originalReturnStatement);

        for (JSProperty property : properties) {
            String propertyStatement = String.format("\t\tutil.%s = %s;", property.getName(), property.getValue().getText());
            node = JSChangeUtil.createExpressionFromText(parent.getProject(), propertyStatement, JSUtils.getDialect(parent.getContainingFile()));
            parent.addBefore(node.getPsi(), originalReturnStatement);
        }

        originalReturnStatement.delete();
    }
}

@@ -2710,17 +2710,16 @@
 .%25s = %25s
-;
 %22, prope
@@ -2757,32 +2757,32 @@
 e().getText());%0A
+
             node
@@ -2985,25 +2985,489 @@
 t);%0A        
-%7D
+    node = JSChangeUtil.createStatementFromText(parent.getProject(), %22;%5Cn%22, JSUtils.getDialect(parent.getContainingFile()));%0A            parent.addBefore(node.getPsi(), originalReturnStatement);%0A        %7D%0A%0A        String newReturnStatement = %22return util;%22;%0A        node = JSChangeUtil.createStatementFromText(parent.getProject(), newReturnStatement, JSUtils.getDialect(parent.getContainingFile()));%0A        parent.addBefore(node.getPsi(), originalReturnStatement);
 %0A%0A        or

add final return statement