package fr.adrienbrault.idea.symfony2plugin.tests.completion.yaml;

import com.intellij.patterns.PlatformPatterns;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
import org.jetbrains.yaml.YAMLFileType;

import java.util.ArrayList;
import java.util.Collection;

/**
 * @author Daniel Espendiller <daniel@espendiller.net>
 * @see fr.adrienbrault.idea.symfony2plugin.completion.yaml.YamlGotoCompletionRegistrar
 */
public class YamlGotoCompletionRegistrarTest extends SymfonyLightCodeInsightFixtureTestCase {
    public void setUp() throws Exception {
        super.setUp();
        myFixture.copyFileToProject("routes.xml");
        myFixture.copyFileToProject("services.xml");
        myFixture.copyFileToProject("YamlGotoCompletionRegistrar.php");
    }

    public String getTestDataPath() {
        return "src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/completion/yaml/fixtures";
    }

    public void testThatRouteInsideRouteDefaultKeyCompletedAndNavigable() {
        assertCompletionContains(YAMLFileType.YML, "" +
            "root:\n" +
            "    path: /wp-admin\n" +
            "    defaults:\n" +
            "        route: '<caret>'\n",
            "foo_route"
        );

        assertNavigationMatch(YAMLFileType.YML, "" +
                "root:\n" +
                "    path: /wp-admin\n" +
                "    defaults:\n" +
                "        route: 'foo_<caret>route'\n"
        );
    }

    public void testThatTemplateInsideRouteDefaultKeyCompletedAndNavigable() {
        if(System.getenv("PHPSTORM_ENV") != null) return;

        try {
            createDummyFiles("app/Resources/views/foo.html.twig");
        } catch (Exception e) {
            e.printStackTrace();
        }

        assertCompletionContains(YAMLFileType.YML, "" +
                "root:\n" +
                "    path: /wp-admin\n" +
                "    defaults:\n" +
                "        template: '<caret>'\n",
            "foo.html.twig"
        );

        assertNavigationMatch(YAMLFileType.YML, "" +
            "root:\n" +
            "    path: /wp-admin\n" +
            "    defaults:\n" +
            "        template: 'foo.ht<caret>ml.twig'\n"
        );
    }

    public void testThatDecoratesServiceTagProvidesReferences() {
        Collection<String[]> strings = new ArrayList<>() {{
            add(new String[]{"<caret>", "foo.bar<caret>_factory"});
            add(new String[]{"'<caret>'", "'foo.bar<caret>_factory'"});
            add(new String[]{"\"<caret>\"", "\"foo.bar<caret>_factory\""});
        }};

        for (String[] s : strings) {
            assertCompletionContains(YAMLFileType.YML, "" +
                    "services:\n" +
                    "    foo:\n" +
                    "       class: Foo\\Foobar\n" +
                    "       decorates: " + s[0] + "\n",
                "foo.bar_factory"
            );

            assertNavigationMatch(YAMLFileType.YML, "" +
                    "services:\n" +
                    "    foo:\n" +
                    "       class: Foo\\Foobar\n" +
                    "       decorates: " + s[1] + "\n",
                PlatformPatterns.psiElement(PhpClass.class)
            );
        }
    }

    public void testThatDecoratesPrioritizeLookupElementOnInstance() {
        assertCompletionLookupContainsPresentableItem(YAMLFileType.YML, "" +
                "services:\n" +
                "    foo:\n" +
                "       class: Foo\\Foobar\n" +
                "       decorates: <caret>\n",
            lookupElement -> "foo".equals(lookupElement.getItemText()) && lookupElement.isItemTextBold() && lookupElement.isItemTextBold()
        );
    }

    public void testThatPhpConstAreCompletedAndNavigable() {
        assertCompletionContains(
            YAMLFileType.YML,
            "services:\n" +
            "    foo:\n" +
            "       class: Foo\\Foobar\n" +
            "       arguments: \n" +
            "           - !php/const <caret>\n",
            "Bar", "Foobar"
        );

        assertCompletionContains(
            YAMLFileType.YML,
            "services:\n" +
            "    foo:\n" +
            "       class: Foo\\Foobar\n" +
            "       arguments: \n" +
            "           - !php/const Foo\\Bar::<caret>\n",
            "BAZ"
        );

        assertCompletionNotContains(
            YAMLFileType.YML,
            "services:\n" +
            "    foo:\n" +
            "       class: Foo\\Foobar\n" +
            "       arguments: \n" +
            "           - !php/const Foo\\Bar::<caret>\n",
            "PROTECTED_CONST", "PRIVATE_CONST"
        );

        assertCompletionIsEmpty(
            YAMLFileType.YML,
            "services:\n" +
            "    foo:\n" +
            "       class: Foo\\Foobar\n" +
            "       arguments: \n" +
            "           - !php/const Foo\\Bar<caret>::BAZ\n"
        );
    }
}
