/* ====================================================================
   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.poi.hwpf.usermodel;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.HWPFTestDataSamples;
import org.apache.poi.hwpf.model.PAPX;
import org.apache.poi.hwpf.model.StyleSheet;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
 * Tests to ensure that our ranges end up with
 *  the right text in them, and the right font/styling
 *  properties applied to them.
 */
public final class TestRangeProperties {
    private static final char page_break = (char)12;

    private static final String u_page_1 =
        "This is a fairly simple word document, over two pages, with headers and footers.\r" +
        "The trick with this one is that it contains some Unicode based strings in it.\r" +
        "Firstly, some currency symbols:\r" +
        "\tGBP - \u00a3\r" +
        "\tEUR - \u20ac\r" +
        "Now, we\u2019ll have some French text, in bold and big:\r" +
        "\tMoli\u00e8re\r" +
        "And some normal French text:\r" +
        "\tL'Avare ou l'\u00c9cole du mensonge\r" +
        "That\u2019s it for page one\r"
    ;
    private static final String u_page_2 =
        "This is page two. Les Pr\u00e9cieuses ridicules. The end.\r"
    ;

    private static final String a_page_1 =
        "I am a test document\r" +
        "This is page 1\r" +
        "I am Calibri (Body) in font size 11\r"
    ;
    private static final String a_page_2 =
        "This is page two\r" +
        "It\u2019s Arial Black in 16 point\r" +
        "It\u2019s also in blue\r"
    ;

    private HWPFDocument u;
    private HWPFDocument a;

    @BeforeEach
    void setUp() {
        u = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc");
        a = HWPFTestDataSamples.openSampleFile("SampleDoc.doc");
    }

    @Test
    void testAsciiTextParagraphs() {
        Range r = a.getRange();
        assertEquals(
                a_page_1 +
                page_break + "\r" +
                a_page_2,
                r.text()
        );

        assertEquals(1, r.numSections());
        assertEquals(1, a.getSectionTable().getSections().size());
        Section s = r.getSection(0);
        assertEquals(
                a_page_1 +
                page_break + "\r" +
                a_page_2,
                s.text()
        );

        // no PAP reconstruction
        // assertEquals( 7, r.numParagraphs() );
        // with PAP reconstructon
        assertEquals( 8, r.numParagraphs() );

        String[] p1_parts = a_page_1.split("\r");
        String[] p2_parts = a_page_2.split("\r");

        // Check paragraph contents
        assertEquals(
                p1_parts[0] + "\r",
                r.getParagraph(0).text()
        );
        assertEquals(
                p1_parts[1] + "\r",
                r.getParagraph(1).text()
        );
        assertEquals(
                p1_parts[2] + "\r",
                r.getParagraph(2).text()
        );

        // no PAPX reconstruction
        // assertEquals( page_break + "\r", r.getParagraph( 3 ).text() );
        // assertEquals( p2_parts[0] + "\r", r.getParagraph( 4 ).text() );
        // assertEquals( p2_parts[1] + "\r", r.getParagraph( 5 ).text() );
        // assertEquals( p2_parts[2] + "\r", r.getParagraph( 6 ).text() );

        // with PAPX reconstruction
        assertEquals( "" + page_break, r.getParagraph( 3 ).text() );
        assertEquals( "\r", r.getParagraph( 4 ).text() );
        assertEquals( p2_parts[0] + "\r", r.getParagraph( 5 ).text() );
        assertEquals( p2_parts[1] + "\r", r.getParagraph( 6 ).text() );
        assertEquals( p2_parts[2] + "\r", r.getParagraph( 7 ).text() );
    }

    @Test
    void testAsciiStyling() {
        Range r = a.getRange();

        Paragraph p1 = r.getParagraph(0);
        Paragraph p7 = r.getParagraph(6);

        assertEquals(1, p1.numCharacterRuns());
        assertEquals(1, p7.numCharacterRuns());

        CharacterRun c1 = p1.getCharacterRun(0);
        CharacterRun c7 = p7.getCharacterRun(0);

        assertEquals("Times New Roman", c1.getFontName()); // No Calibri
        assertEquals("Arial Black", c7.getFontName());
        assertEquals(22, c1.getFontSize());
        assertEquals(32, c7.getFontSize());

        // This document has 15 styles
        assertEquals(15, a.getStyleSheet().numStyles());

        // Ensure none of the paragraphs refer to one that isn't there,
        //  and none of their character runs either
        // Also check all use the default style
        StyleSheet ss = a.getStyleSheet();
        for(int i=0; i<a.getRange().numParagraphs(); i++) {
            Paragraph p = a.getRange().getParagraph(i);
            int styleIndex = p.getStyleIndex();
            assertTrue(styleIndex < 15);
            assertEquals("Normal", ss.getStyleDescription(styleIndex).getName());
        }
        for(int i=0; i<a.getRange().numCharacterRuns(); i++) {
            CharacterRun c = a.getRange().getCharacterRun(i);
            int styleIndex = c.getStyleIndex();
            assertTrue(styleIndex < 15);
            assertEquals("Normal", ss.getStyleDescription(styleIndex).getName());
        }
    }

    /**
     * Tests the raw definitions of the paragraphs of
     *  a unicode document
     */
    @Test
    void testUnicodeParagraphDefinitions() {
        Range r = u.getRange();
        String[] p1_parts = u_page_1.split("\r");

        assertEquals(
                u_page_1 + page_break + "\r" + u_page_2,
                r.text()
        );
        assertEquals(
                408, r.text().length()
        );


        assertEquals(1, r.numSections());
        assertEquals(1, u.getSectionTable().getSections().size());
        Section s = r.getSection(0);
        assertEquals(
                u_page_1 +
                page_break + "\r" +
                u_page_2,
                s.text()
        );
        assertEquals(0, s.getStartOffset());
        assertEquals(408, s.getEndOffset());


        List<PAPX> pDefs = r._paragraphs;
        // no PAPX reconstruction
        // assertEquals(36, pDefs.size());
        // with PAPX reconstruction
        assertEquals( 36, pDefs.size() );

        // Check that the last paragraph ends where it should do
        assertEquals(531, u.getOverallRange().text().length());
        PAPX pLast = pDefs.get(34);
        assertEquals(530, pLast.getEnd());

        // Only care about the first few really though
        PAPX p0 = pDefs.get(0);
        PAPX p1 = pDefs.get(1);
        PAPX p2 = pDefs.get(2);
        PAPX p3 = pDefs.get(3);
        PAPX p4 = pDefs.get(4);

        // 5 paragraphs should get us to the end of our text
        assertTrue(p0.getStart() < 408);
        assertTrue(p0.getEnd() < 408);
        assertTrue(p1.getStart() < 408);
        assertTrue(p1.getEnd() < 408);
        assertTrue(p2.getStart() < 408);
        assertTrue(p2.getEnd() < 408);
        assertTrue(p3.getStart() < 408);
        assertTrue(p3.getEnd() < 408);
        assertTrue(p4.getStart() < 408);
        assertTrue(p4.getEnd() < 408);

        // Paragraphs should match with lines
        assertEquals(
                0,
                p0.getStart()
        );
        assertEquals(
                p1_parts[0].length() + 1,
                p0.getEnd()
        );

        assertEquals(
                p1_parts[0].length() + 1,
                p1.getStart()
        );
        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1,
                p1.getEnd()
        );

        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1,
                p2.getStart()
        );
        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1 +
                p1_parts[2].length() + 1,
                p2.getEnd()
        );
	}

    /**
     * Tests the paragraph text of a unicode document
     */
    @Test
    void testUnicodeTextParagraphs() {
        Range r = u.getRange();
        assertEquals(
                u_page_1 +
                page_break + "\r" +
                u_page_2,
                r.text()
        );

        // without PAPX reconstruction
        // assertEquals( 12, r.numParagraphs() );
        // with PAPX reconstruction
        assertEquals( 13, r.numParagraphs() );
        String[] p1_parts = u_page_1.split("\r");
        String[] p2_parts = u_page_2.split("\r");

        // Check text all matches up properly
        assertEquals(p1_parts[0] + "\r", r.getParagraph(0).text());
        assertEquals(p1_parts[1] + "\r", r.getParagraph(1).text());
        assertEquals(p1_parts[2] + "\r", r.getParagraph(2).text());
        assertEquals(p1_parts[3] + "\r", r.getParagraph(3).text());
        assertEquals(p1_parts[4] + "\r", r.getParagraph(4).text());
        assertEquals(p1_parts[5] + "\r", r.getParagraph(5).text());
        assertEquals(p1_parts[6] + "\r", r.getParagraph(6).text());
        assertEquals(p1_parts[7] + "\r", r.getParagraph(7).text());
        assertEquals(p1_parts[8] + "\r", r.getParagraph(8).text());
        assertEquals(p1_parts[9] + "\r", r.getParagraph(9).text());
        // without PAPX reconstruction
        // assertEquals(page_break + "\r", r.getParagraph(10).text());
        // assertEquals(p2_parts[0] + "\r", r.getParagraph(11).text());
        // with PAPX reconstruction
        assertEquals( page_break + "", r.getParagraph( 10 ).text() );
        assertEquals( "\r", r.getParagraph( 11 ).text() );
        assertEquals( p2_parts[0] + "\r", r.getParagraph( 12 ).text() );
    }

    @Test
    void testUnicodeStyling() {
        Range r = u.getRange();
        String[] p1_parts = u_page_1.split("\r");

        Paragraph p1 = r.getParagraph(0);
        Paragraph p7 = r.getParagraph(6);
        StyleSheet ss = r._doc.getStyleSheet();

        // Line ending in its own run each time!
        assertEquals(2, p1.numCharacterRuns());
        assertEquals(2, p7.numCharacterRuns());

        CharacterRun c1a = p1.getCharacterRun(0);
        CharacterRun c1b = p1.getCharacterRun(1);
        CharacterRun c7a = p7.getCharacterRun(0);
        CharacterRun c7b = p7.getCharacterRun(1);

        assertEquals("Times New Roman", c1a.getFontName()); // No Calibri
        assertEquals(22, c1a.getFontSize());

        assertEquals("Times New Roman", c1b.getFontName()); // No Calibri
        assertEquals(22, c1b.getFontSize());

        assertEquals("Times New Roman", c7a.getFontName());
        assertEquals(48, c7a.getFontSize());

        assertEquals("Times New Roman", c7b.getFontName());
        assertEquals(48, c7b.getFontSize());

        // All use the default base style
        assertEquals("Normal", ss.getStyleDescription(c1a.getStyleIndex()).getName());
        assertEquals("Normal", ss.getStyleDescription(c1b.getStyleIndex()).getName());
        assertEquals("Heading 1", ss.getStyleDescription(c7a.getStyleIndex()).getName());
        assertEquals("Heading 1", ss.getStyleDescription(c7b.getStyleIndex()).getName());

        // Now check where they crop up
        assertEquals(
                0,
                c1a.getStartOffset()
        );
        assertEquals(
                p1_parts[0].length(),
                c1a.getEndOffset()
        );

        assertEquals(
                p1_parts[0].length(),
                c1b.getStartOffset()
        );
        assertEquals(
                p1_parts[0].length()+1,
                c1b.getEndOffset()
        );

        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1 +
                p1_parts[2].length() + 1 +
                p1_parts[3].length() + 1 +
                p1_parts[4].length() + 1 +
                p1_parts[5].length() + 1,
                c7a.getStartOffset()
        );
        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1 +
                p1_parts[2].length() + 1 +
                p1_parts[3].length() + 1 +
                p1_parts[4].length() + 1 +
                p1_parts[5].length() + 1 +
                1,
                c7a.getEndOffset()
        );

        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1 +
                p1_parts[2].length() + 1 +
                p1_parts[3].length() + 1 +
                p1_parts[4].length() + 1 +
                p1_parts[5].length() + 1 +
                1,
                c7b.getStartOffset()
        );
        assertEquals(
                p1_parts[0].length() + 1 +
                p1_parts[1].length() + 1 +
                p1_parts[2].length() + 1 +
                p1_parts[3].length() + 1 +
                p1_parts[4].length() + 1 +
                p1_parts[5].length() + 1 +
                p1_parts[6].length() + 1,
                c7b.getEndOffset()
        );

        // This document also has 22 styles
        assertEquals(22, ss.numStyles());

        // Ensure none of the paragraphs refer to one that isn't there,
        //  and none of their character runs either
        for(int i=0; i<r.numParagraphs(); i++) {
            Paragraph p = r.getParagraph(i);
            int styleIndex = p.getStyleIndex();
            assertTrue(styleIndex < 22);
            assertNotNull(ss.getStyleDescription(styleIndex).getName());
        }
        for(int i=0; i<r.numCharacterRuns(); i++) {
            CharacterRun c = r.getCharacterRun(i);
            int styleIndex = c.getStyleIndex();
            assertTrue(styleIndex < 22);
            assertNotNull(ss.getStyleDescription(styleIndex).getName());
        }
    }
}
