package org.apache.maven.doxia.module.twiki.parser;

/*
 * 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.
 */

import java.io.StringReader;
import java.util.Arrays;

import org.apache.maven.doxia.util.ByLineReaderSource;
import org.apache.maven.doxia.parser.ParseException;

/**
 * Tests the {@link org.apache.maven.doxia.module.twiki.parser.SectionBlockParser}
 *
 * @author Juan F. Codagnone
 * @since Nov 1, 2005
 */
public class SectionTest
    extends AbstractBlockTestCase
{

    /**
     * @see SectionBlock#SectionBlock(String, int, Block[])
     */
    public final void testSectionBlockWrongArgs()
    {
        final int maxLevel = 5;
        new SectionBlock( "hola", 1, new Block[] {} );
        new SectionBlock( "hola", maxLevel, new Block[] {} );

        try
        {
            new SectionBlock( "hola", maxLevel + 1, new Block[] {} );
            fail();
        }
        catch ( final Throwable e )
        {
            // ok
        }

        try
        {
            new SectionBlock( "hola", 0, new Block[] {} );
            fail();
        }
        catch ( final Throwable e )
        {
            // ok
        }

        try
        {
            new SectionBlock( null, 1, null );
            fail();
        }
        catch ( final Throwable e )
        {
            // ok
        }

        new SectionBlock( "", 1, new Block[] {} );
    }

    /**
     * @see SectionBlockParser#getLevel(String)
     */
    public final void testSectionParserGetLevel()
    {
        assertEquals( 2, SectionBlockParser.getLevel( "++" ) );
        try
        {
            SectionBlockParser.getLevel( "asdasd" );
            fail( "expected exception was not thrown" );
        }
        catch ( IllegalArgumentException e )
        {
            // ok
        }
    }

    /**
     * @throws java.lang.Exception
     * @see SectionBlockParser
     */
    public final void testSectionParser()
        throws Exception
    {
        final SectionBlockParser parser = sectionParser;
        assertTrue( parser.accept( "---+ Title1" ) );
        assertTrue( parser.accept( "---++ Title2" ) );
        assertFalse( parser.accept( " ---++ Title3" ) );
        assertTrue( parser.accept( "---+++ Title4" ) );
        assertTrue( parser.accept( "---++++ Title5" ) );
        assertTrue( parser.accept( "---+++++ Title6" ) );

        SectionBlock block;
        block = (SectionBlock) parser.visit( "---++++ Title4", new ByLineReaderSource( new StringReader( "" ) ) );

        final int level = 4;
        assertEquals( "Title4", block.getTitle() );
        assertEquals( level, block.getLevel() );
        assertEquals( 0, block.getBlocks().length );

        // ejemplo un poco m�s complejo
        block =
            (SectionBlock) parser.visit( "---+++ Title3",
                                         new ByLineReaderSource( new StringReader(
                                                                                   "This is *a* parragraph of a section.\n"
                                                                                       + "Some text.\n"
                                                                                       + "---+++ Another Title"
                                                                                       + "... and more text" ) ) );
        final SectionBlock expected =
            new SectionBlock( "Title3", 3, new Block[] { new ParagraphBlock( new Block[] {
                new TextBlock( "This is " ), new BoldBlock( new Block[] { new TextBlock( "a" ) } ),
                new TextBlock( " parragraph of a section. Some text." ) } ) } );
        assertEquals( expected, block );
    }

    /**
     * Test section with several paragraphs (the paragraph are plain text)
     *
     * @throws Exception on error
     */
    public final void testSectionWithParagraphs()
        throws Exception
    {
        final String text =
            "" + "---++ Title\n" + "\n" + "hey!\n" + "how are\n" + "you?\n" + "  \n  " + "Fine!! thanks";

        final SectionBlockParser parser = sectionParser;
        parser.setVerbatimBlockParser( new VerbatimBlockParser() );
        final ByLineReaderSource source = new ByLineReaderSource( new StringReader( text ) );
        final SectionBlock block = (SectionBlock) parser.visit( source.getNextLine(), source );
        assertEquals( 2, block.getBlocks().length );
        assertEquals( "hey! how are you?",
                      ( (TextBlock) ( (ParagraphBlock) block.getBlocks()[0] ).getBlocks()[0] ).getText() );
        assertEquals( "Fine!! thanks",
                      ( (TextBlock) ( (ParagraphBlock) block.getBlocks()[1] ).getBlocks()[0] ).getText() );
    }

    /**
     * @throws ParseException on error
     */
    public final void testSectionAndParaAndHrule()
        throws ParseException
    {
        Block[] blocks, expected;
        ByLineReaderSource source;

        source =
            new ByLineReaderSource( new StringReader( "" + "---++ Title\n" + "Some text\n"
                + "----------- More text\n" ) );
        expected =
            new Block[] { new SectionBlock( "Title", 1, new Block[] {
                new ParagraphBlock( new Block[] { new TextBlock( "Some text" ) } ), new HorizontalRuleBlock(),
                new ParagraphBlock( new Block[] { new TextBlock( "More text" ) } ) } ) };
        blocks = twikiParser.parse( source ).toArray( new Block[] {} );
        assertTrue( Arrays.equals( expected, blocks ) );
    }
}
