/*******************************************************************************
 * Copyright (c) 2006, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Mickael Istria (Red Hat Inc.) - [509032] Support additional tags
 *******************************************************************************/
package org.eclipse.jface.text.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;

import org.eclipse.jface.internal.text.html.HTML2TextReader;

import org.eclipse.jface.text.TextPresentation;

public class HTML2TextReaderTest {

	private static final boolean DEBUG= false;

	private static final String LD= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$


	/**
	 * @param input input
	 * @param expectedOutput expected output
	 * @param styleRangeCount count
	 * @throws IOException test failure
	 * @deprecated pass actual style ranges
	 */
	@Deprecated
	private void verify(String input, String expectedOutput, int styleRangeCount) throws IOException {
		Reader reader= new StringReader(input);
		TextPresentation textPresentation= new TextPresentation();
		String result;
		try (HTML2TextReader htmlReader= new HTML2TextReader(reader, textPresentation)) {
			result= htmlReader.getString();
		}
		if (DEBUG)
			System.out.println("<" + result + "/>");
		assertEquals(expectedOutput, result);

		Iterator<StyleRange> styleRangeIterator= textPresentation.getAllStyleRangeIterator();
		List<StyleRange> ranges= new ArrayList<>();
		while (styleRangeIterator.hasNext()) {
			ranges.add(styleRangeIterator.next());
		}

		assertEquals("Incorrect number of style ranges", styleRangeCount, ranges.size());

		Collections.sort(ranges, (r1, r2) -> r1.start - r2.start);

		for (int i= 0; i < ranges.size() - 1; i++) {
			StyleRange range1= ranges.get(i);
			StyleRange range2= ranges.get(i + 1);

			if (range1.start + range1.length > range2.start) {
				assertTrue("StyleRanges overlap", false);
			}
		}

	}

	private void verify(String input, String expectedOutput, StyleRange[] styleRanges) throws IOException {
		Reader reader= new StringReader(input);
		TextPresentation textPresentation= new TextPresentation();
		String result;
		try (HTML2TextReader htmlReader= new HTML2TextReader(reader, textPresentation)) {
			result= htmlReader.getString();
		}
		if (DEBUG)
			System.out.println("<" + result + "/>");
		assertEquals(expectedOutput, result);

		Iterator<StyleRange> styleRangeIterator= textPresentation.getAllStyleRangeIterator();
		List<StyleRange> ranges= new ArrayList<>();
		while (styleRangeIterator.hasNext()) {
			ranges.add(styleRangeIterator.next());
		}

		Collections.sort(ranges, (r1, r2) -> r1.start - r2.start);

		assertEquals(Arrays.asList(styleRanges), ranges);

		for (int i= 0; i < ranges.size() - 1; i++) {
			StyleRange range1= ranges.get(i);
			StyleRange range2= ranges.get(i + 1);

			if (range1.start + range1.length > range2.start) {
				assertTrue("StyleRanges overlap", false);
			}
		}

	}

	@Test
	public void test0() throws IOException{
		String string= "<code>3<5<code>";
		String expected= "3<5";
		verify(string, expected, 0);
	}

	@Test
	public void test1() throws IOException{
		String string= "<dl><dt>@author</dt><dd>Foo Bar</dd></dl>";
		String expected= LD+ "@author"+LD+"\tFoo Bar"+LD;
		verify(string, expected, 1);
	}

	@Test
	public void test2() throws IOException{
		String string= "<code>3>5<code>";
		String expected= "3>5";
		verify(string, expected, 0);
	}

	@Test
	public void test3() throws IOException{
		String string= "<a href= \"<p>this is only a string - not a tag<p>\">text</a>";
		String expected= "text";
		verify(string, expected, 0);
	}

	@Test
	public void test4() throws IOException{
		String string= 	"<html><body text=\"#000000\" bgcolor=\"#FFFF88\"><font size=-1><h5>void p.Bb.fes()</h5><p><dl><dt>Parameters:</dt><dd><b>i</b> fred or <code>null</code></dd></dl></font></body></html>";
		String expected= "void p.Bb.fes()"+ LD + LD + LD+ "Parameters:"+ LD + "\ti fred or null"+LD;
		verify(string, expected, 3);
	}

	@Test
	public void test5() throws IOException{
		String string= "<code>1<2<3<4</code>";
		String expected= "1<2<3<4";
		verify(string, expected, 0);
	}

	@Test
	public void test6() throws IOException{
		//test for bug 19070
		String string= "<p>Something.<p>Something more.";
		String expected= LD + "Something." + LD + "Something more.";
		verify(string, expected, 0);
	}

	@Test
	public void testEntity1() throws IOException {
		String string= "&amp;";
		String expected= "&";
		verify(string, expected, 0);
	}

	@Test
	public void testEntity2() throws IOException {
		String string= "&unknown;";
		String expected= "&unknown;";
		verify(string, expected, 0);
	}

	@Test
	public void testBug367378() throws IOException {
		verify("<head>", "", 0);
		verify("<head>some styles</html>", "", 0);

		char[] cb= new char[20];
		StringReader reader= new StringReader("<head>");
		try (HTML2TextReader r= new HTML2TextReader(reader, null)) {
			r.read(cb);
		}
		assertTrue(Arrays.equals(new char[20], cb));
	}

	@Test
	public void testComments() throws Exception {
		String string= "<!-- begin-user-doc -->no comment<!-- end-user-doc -->";
		String expected= "no comment";
		verify(string, expected, 0);
	}

	@Test
	public void testStyles1() throws IOException {
		String string= "<b>Hello World</b>";
		String expected= "Hello World";
		verify(string, expected, 1);
	}

	@Test
	public void testStyles2() throws IOException {
		String string= "<del>Hello World</del>";
		String expected= "Hello World";
		verify(string, expected, 1);
	}

	@Test
	public void testStyles3() throws IOException {
		String string= "<b><del>Hello World</del></b>";
		String expected= "Hello World";
		verify(string, expected, 1);
	}

	@Test
	public void testStyles4() throws IOException {
		String string= "<del><b>Hello World</b></del>";
		String expected= "Hello World";
		verify(string, expected, 1);
	}

	@Test
	public void testStyles5() throws IOException {
		String string= "<b>This <del> is a </del> test</b>";
		String expected= "This is a test";
		verify(string, expected, 3);
	}

	@Test
	public void testStyles6() throws IOException {
		String string= "<del>This <b> is a </b> test</del>";
		String expected= "This is a test";
		verify(string, expected, 3);
	}

	@Test
	public void testStyles7() throws IOException {
		String string= "<b>This<del>is a</del>test</b>";
		String expected= "Thisis atest";
		verify(string, expected, 3);
	}

	@Test
	public void testStyles8() throws IOException {
		String string= "<del>This<b>is a</b>test</del>";
		String expected= "Thisis atest";
		verify(string, expected, 3);
	}

	@Test
	public void testStyles9() throws IOException {
		String string= "<b>This <del>is <b>yet</b> another</del> test</b>";
		String expected= "This is yet another test";
		verify(string, expected, 3);
	}

	@Test
	public void testStyles10() throws IOException {
		String string= "<del>This <b>is <del>yet</del> another </b>test</del>";
		String expected= "This is yet another test";
		verify(string, expected, 3);
	}

	@Test
	public void testStylesWithPre() throws IOException {
		String string= "I am <b>bold</b>." + LD + "<p>" + LD + "<pre>One" + LD + LD + "<b>T</b>hree.</pre>" + LD + "<p>" + LD + "<b>Author:</b> me.";
		String expected= "I am bold. " + LD + "One" + LD + LD + "Three. " + LD + "Author: me.";
		StyleRange[] ranges= {
				new StyleRange(5, 4, null, null, SWT.BOLD),
				new StyleRange(14 + 3*LD.length(), 1, null, null, SWT.BOLD),
				new StyleRange(21 + 4*LD.length(), 7, null, null, SWT.BOLD)
		};
		verify(string, expected, ranges);
	}

	@Test
	public void testCombineBoldItalicStriker() throws IOException {
		String string= "<strong>strong</strong>,<em>italic</em>,<s>strike</s>," +
				"<strong><em>strongItalic</em></strong>,<s><strong>strongStrike</strong></s>," +
				"<em><s>italicStrike</s></em>," +
				"<em><strong><s>strongItalicStrike</s></strong></em>," +
				"none";
		String expected= "strong,italic,strike,strongItalic,strongStrike,italicStrike,strongItalicStrike,none";
		StyleRange[] ranges= {
				new StyleRange(0, 6, null, null, SWT.BOLD),
				new StyleRange(7, 6, null, null, SWT.ITALIC),
				strike(new StyleRange(14, 6, null, null)),
				new StyleRange(21, 12, null, null, SWT.BOLD | SWT.ITALIC),
				strike(new StyleRange(34, 12, null, null, SWT.BOLD)),
				strike(new StyleRange(47, 12, null, null, SWT.ITALIC)),
				strike(new StyleRange(60, 18, null, null, SWT.BOLD | SWT.ITALIC)),
		};
		verify(string, expected, ranges);
	}

	private StyleRange strike(StyleRange styleRange) {
		styleRange.strikeout = true;
		return styleRange;
	}
}

