/*
 * Copyright 2016 Open Networking Laboratory
 *
 * 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.onosproject.yangutils.utils.io.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.getJavaDoc;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.BUILDER_CLASS;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.BUILDER_INTERFACE;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.BUILD_METHOD;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.CONSTRUCTOR;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.DEFAULT_CONSTRUCTOR;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.GETTER_METHOD;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.IMPL_CLASS;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.INTERFACE;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.PACKAGE_INFO;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.SETTER_METHOD;
import static org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType.TYPE_DEF_SETTER_METHOD;

/**
 * Tests the java doc that is generated.
 */
public final class JavaDocGenTest {

    private static final String TEST_NAME = "testName";
    private static final String END_STRING = " */\n";

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    /**
     * This test case checks the content recieved for the builder class java doc.
     */
    @Test
    public void builderClassGenerationTest() {
        String builderClassJavaDoc = getJavaDoc(BUILDER_CLASS, TEST_NAME, false);
        assertThat(true, is(builderClassJavaDoc.contains("Reperesents the builder implementation of")
                && builderClassJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the builder interface ge java doc.
     */
    @Test
    public void builderInterfaceGenerationTest() {
        String builderInterfaceJavaDoc = getJavaDoc(BUILDER_INTERFACE, TEST_NAME, false);
        assertThat(true,
                is(builderInterfaceJavaDoc.contains("Builder for") && builderInterfaceJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the build  java doc.
     */
    @Test
    public void buildGenerationTest() {
        String buildDoc = getJavaDoc(BUILD_METHOD, TEST_NAME, false);
        assertThat(true, is(buildDoc.contains("Builds object of") && buildDoc.contains(END_STRING)));
    }

    /**
     * A private constructor is tested.
     *
     * @throws SecurityException if any security violation is observed
     * @throws NoSuchMethodException if when the method is not found
     * @throws IllegalArgumentException if there is illegal argument found
     * @throws InstantiationException if instantiation is provoked for the private constructor
     * @throws IllegalAccessException if instance is provoked or a method is provoked
     * @throws InvocationTargetException when an exception occurs by the method or constructor
     */
    @Test
    public void callPrivateConstructors() throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            InstantiationException, IllegalAccessException, InvocationTargetException {

        Class<?>[] classesToConstruct = {JavaDocGen.class };
        for (Class<?> clazz : classesToConstruct) {
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(true);
            assertThat(null, not(constructor.newInstance()));
        }
    }

    /**
     * This test case checks the content recieved for the constructor java doc.
     */
    @Test
    public void constructorGenerationTest() {
        String constructorDoc = getJavaDoc(CONSTRUCTOR, TEST_NAME, false);
        assertThat(true,
                is(constructorDoc.contains("Creates an instance of ") && constructorDoc.contains("builder object of")
                        && constructorDoc.contains("@param") && constructorDoc.contains("*/\n")));
    }

    /**
     * This test case checks the content recieved for the default constructor java doc.
     */
    @Test
    public void defaultConstructorGenerationTest() {
        String defaultConstructorDoc = getJavaDoc(DEFAULT_CONSTRUCTOR, TEST_NAME, false);
        assertThat(true, is(defaultConstructorDoc.contains("Creates an instance of ")
                && defaultConstructorDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the getter java doc.
     */
    @Test
    public void getterGenerationTest() {
        String getterJavaDoc = getJavaDoc(GETTER_METHOD, TEST_NAME, false);
        assertThat(true, is(getterJavaDoc.contains("Returns the attribute") && getterJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the impl class java doc.
     */
    @Test
    public void implClassGenerationTest() {
        String implClassJavaDoc = getJavaDoc(IMPL_CLASS, TEST_NAME, false);
        assertThat(true,
                is(implClassJavaDoc.contains("Reperesents the implementation of")
                        && implClassJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the interface java doc.
     */
    @Test
    public void interfaceGenerationTest() {
        String interfaceJavaDoc = getJavaDoc(INTERFACE, TEST_NAME, false);
        assertThat(true,
                is(interfaceJavaDoc.contains("Abstraction of an entity which Reperesents the functionalities of")
                        && interfaceJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the package info  java doc.
     */
    @Test
    public void packageInfoGenerationTest() {
        String packageInfo = getJavaDoc(PACKAGE_INFO, TEST_NAME, false);
        assertThat(true, is(packageInfo.contains("Implementation of YANG file") && packageInfo.contains(END_STRING)));
    }

    /**
     * This test case checks the content recieved for the setter java doc.
     */
    @Test
    public void setterGenerationTest() {
        String setterJavaDoc = getJavaDoc(SETTER_METHOD, TEST_NAME, false);
        assertThat(true,
                is(setterJavaDoc.contains("Returns the builder object of") && setterJavaDoc.contains(END_STRING)));
    }

    /**
     * This test case checks the content received for the typedef setter java doc.
     */
    @Test
    public void typeDefSetterGenerationTest() {
        String typeDefSetter = getJavaDoc(TYPE_DEF_SETTER_METHOD, TEST_NAME, false);
        assertThat(true, is(typeDefSetter.contains("Sets the value of") && typeDefSetter.contains(END_STRING)));
    }
}