/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.maven.plugins.javadoc;

import java.io.StringReader;

import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaSource;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class AbstractFixJavadocMojoTest {
    private JavaSource getJavaSource(String source) {
        return new JavaProjectBuilder().addSource(new StringReader(source));
    }

    @Test
    public void testReplaceLinkTags_noLinkTag() {
        String comment = "/** @see ConnectException */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class NoLinkTag {}";

        JavaClass clazz = getJavaSource(source).getClassByName("NoLinkTag");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);

        assertThat(newComment).isEqualTo("/** @see ConnectException */");
    }

    @Test
    public void testReplaceLinkTags_oneLinkTag() {
        String comment = "/** {@link ConnectException} */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class OneLinkTag {}";

        JavaClass clazz = getJavaSource(source).getClassByName("OneLinkTag");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException} */");
    }

    @Test
    public void testReplaceLinkTags_missingEndBrace() {
        String comment = "/** {@link ConnectException */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class MissingEndBrace {}";

        JavaClass clazz = getJavaSource(source).getClassByName("MissingEndBrace");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link ConnectException */");
    }

    @Test
    public void testReplaceLinkTags_spacesAfterLinkTag() {
        String comment = "/** {@link     ConnectException} */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class SpacesAfterLinkTag {}";

        JavaClass clazz = getJavaSource(source).getClassByName("SpacesAfterLinkTag");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException} */");
    }

    @Test
    public void testReplaceLinkTags_spacesAfterClassName() {
        String comment = "/** {@link ConnectException       } */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class SpacesAfterClassName {}";

        JavaClass clazz = getJavaSource(source).getClassByName("SpacesAfterClassName");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException} */");
    }

    @Test
    public void testReplaceLinkTags_spacesAfterMethod() {
        String comment = "/** {@link ConnectException#getMessage()       } */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class SpacesAfterMethod {}";

        JavaClass clazz = getJavaSource(source).getClassByName("SpacesAfterMethod");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException#getMessage()} */");
    }

    @Test
    public void testReplaceLinkTags_containingHash() {
        String comment = "/** {@link ConnectException#getMessage()} */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class ContainingHashes {}";

        JavaClass clazz = getJavaSource(source).getClassByName("ContainingHashes");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException#getMessage()} */");
    }

    @Test
    public void testReplaceLinkTags_followedByHash() {
        String comment = "/** {@link ConnectException} ##important## */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class FollowedByHash {}";

        JavaClass clazz = getJavaSource(source).getClassByName("FollowedByHash");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** {@link java.net.ConnectException} ##important## */");
    }

    @Test
    public void testReplaceLinkTags_twoLinks() {
        String comment = "/** Use {@link ConnectException} instead of {@link Exception} */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class TwoLinks {}";

        JavaClass clazz = getJavaSource(source).getClassByName("TwoLinks");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment)
                .isEqualTo("/** Use {@link java.net.ConnectException} instead of {@link java.lang.Exception} */");
    }

    @Test
    public void testReplaceLinkTags_OnlyAnchor() {
        String comment = "/** There's a {@link #getClass()} but no setClass() */";
        String source = "import java.net.ConnectException;\n" + comment + "\n" + "public class OnlyAnchor {}";

        JavaClass clazz = getJavaSource(source).getClassByName("OnlyAnchor");

        String newComment = AbstractFixJavadocMojo.replaceLinkTags(comment, clazz);
        assertThat(newComment).isEqualTo("/** There's a {@link #getClass()} but no setClass() */");
    }
}
