/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed 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.uberfire.annotations.processors;

import java.io.FileNotFoundException;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Tests for Pop-up related class generation
 */
public class WorkbenchPopupProcessorTest extends AbstractProcessorTest {

    final Result result = new Result();

    @Override
    protected AbstractErrorAbsorbingProcessor getProcessorUnderTest() {
        return new WorkbenchPopupProcessor(new GenerationCompleteCallback() {

            @Override
            public void generationComplete(String code) {
                result.setActualCode(code);
            }
        });
    }

    @Test
    public void testNoWorkbenchPopupAnnotation() throws FileNotFoundException {
        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                "org/uberfire/annotations/processors/WorkbenchPopupTest1");

        assertSuccessfulCompilation(diagnostics);
        assertNull(result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupAnnotationMissingViewAnnotation() {
        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                "org/uberfire/annotations/processors/WorkbenchPopupTest2");

        assertFailedCompilation(diagnostics);
        assertCompilationMessage(diagnostics,
                                 Kind.ERROR,
                                 Diagnostic.NOPOS,
                                 Diagnostic.NOPOS,
                                 "org.uberfire.annotations.processors.WorkbenchPopupTest2Activity: The WorkbenchPopup must either extend IsWidget or provide a @WorkbenchPartView annotated method to return a com.google.gwt.user.client.ui.IsWidget.");
        assertNull(result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupHasViewAnnotation() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest3";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest3.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupExtendsIsWidget() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest4";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest4.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupHasViewAnnotationAndExtendsIsWidget() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest5";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest5.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertCompilationMessage(diagnostics,
                                 Kind.WARNING,
                                 Diagnostic.NOPOS,
                                 Diagnostic.NOPOS,
                                 "The WorkbenchPopup both extends com.google.gwt.user.client.ui.IsWidget and provides a @WorkbenchPartView annotated method. The annotated method will take precedence.");
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupAllAnnotations() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest6";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest6.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupOnStart0Parameter() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest7";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest7.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupOnStart1Parameter() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest8";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest8.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupOnStartMultipleMethods() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest9";

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertFailedCompilation(diagnostics);
        assertCompilationMessage(diagnostics,
                                 Kind.ERROR,
                                 24,
                                 17,
                                 "Found multiple @OnStartup methods. Each class can declare at most one.");
    }

    @Test
    public void testWorkbenchPopupHasTitleWidget() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest10";

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertFailedCompilation(diagnostics);
        assertCompilationMessage(diagnostics,
                                 Kind.ERROR,
                                 Diagnostic.NOPOS,
                                 Diagnostic.NOPOS,
                                 "org.uberfire.annotations.processors.WorkbenchPopupTest10Activity: The WorkbenchPopup must provide a @WorkbenchPartTitle annotated method to return a java.lang.String.");
        assertNull(result.getActualCode());
    }

    @Test
    public void testWorkbenchPopupHasTitleAndTitleWidget() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest11";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest11.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testPopupWithActivator() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest12";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest12.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testPopupSize() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest13";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest13.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }

    @Test
    public void testQualifiersInTheActivity() throws FileNotFoundException {
        final String pathCompilationUnit = "org/uberfire/annotations/processors/WorkbenchPopupTest14";
        final String pathExpectedResult = "org/uberfire/annotations/processors/expected/WorkbenchPopupTest14.expected";

        result.setExpectedCode(getExpectedSourceCode(pathExpectedResult));

        final List<Diagnostic<? extends JavaFileObject>> diagnostics = compile(
                getProcessorUnderTest(),
                pathCompilationUnit);

        assertSuccessfulCompilation(diagnostics);
        assertNotNull(result.getActualCode());
        assertNotNull(result.getExpectedCode());
        assertEquals(result.getExpectedCode(),
                     result.getActualCode());
    }
}
