// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package com.dom_distiller.client;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;

import de.l3s.boilerpipe.BoilerpipeProcessingException;
import de.l3s.boilerpipe.document.TextBlock;
import de.l3s.boilerpipe.document.TextDocument;
import de.l3s.boilerpipe.extractors.CommonExtractors;
import de.l3s.boilerpipe.labels.DefaultLabels;
import de.l3s.boilerpipe.sax.BoilerpipeHTMLContentHandler;

import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;

import org.xml.sax.AttributesImpl;
import org.xml.sax.SAXException;

@Export()
public class ContentExtractor implements Exportable {
    static Logger logger = Logger.getLogger("DomDistiller");

    public static String extractContent() {
        BoilerpipeHTMLContentHandler htmlParser = new BoilerpipeHTMLContentHandler();
        List<Node> textNodes = null;

        try {
            htmlParser.startDocument();
            Element documentElement = Document.get().getDocumentElement();
            textNodes = DomToSaxParser.parse(documentElement, htmlParser);
            htmlParser.endDocument();
        } catch (SAXException e) {
            logger.warning("Parsing failed.");
            return "";
        }

        TextDocument document = htmlParser.toTextDocument();
        try {
            CommonExtractors.ARTICLE_EXTRACTOR.process(document);
        } catch (BoilerpipeProcessingException e) {
            logger.warning("Processing failed.");
            return "";
        }

        List<Integer> contentTextIndexes = new ArrayList<Integer>();
        for (TextBlock tb : document.getTextBlocks()) {
            if (!tb.hasLabel(DefaultLabels.TITLE)) {
                contentTextIndexes.addAll(tb.getContainedTextElements());
            }
        }
        Collections.sort(contentTextIndexes);

        // Boilerpipe's text node indexes start at 1.
        List<Node> contentNodes = new ArrayList<Node>(contentTextIndexes.size());
        for (Integer i : contentTextIndexes) {
            contentNodes.add(textNodes.get(i - 1));
        }

        List<Node> contentAndImages = RelevantImageFinder.findAndAddImages(
                contentNodes, Document.get().getDocumentElement());

        Node clonedSubtree = NodeListExpander.expand(contentAndImages).cloneSubtree();

        if (clonedSubtree.getNodeType() != Node.ELEMENT_NODE) {
            return "";
        }

        makeAllLinksAbsolute(clonedSubtree);

        // TODO(cjhopman): this discards the top element and just returns its children. This might
        // break in some cases.
        return Element.as(clonedSubtree).getInnerHTML();
    }

    private static void makeAllLinksAbsolute(Node rootNode) {
        Element root = Element.as(rootNode);
        NodeList<Element> allLinks = root.getElementsByTagName("A");
        for (int i = 0; i < allLinks.getLength(); i++) {
            AnchorElement link = AnchorElement.as(allLinks.getItem(i));
            link.setHref(link.getHref());
        }
    }
}

@@ -434,32 +434,79 @@
 client.Element;%0A
+import com.google.gwt.dom.client.ImageElement;%0A
 import com.googl
@@ -2867,32 +2867,253 @@
  %22%22;%0A        %7D%0A%0A
+        // The base URL in the distilled page viewer is different from that in%0A        // the live page.  This breaks all relative links (in anchors and%0A        // images), so make them absolute in the distilled content.%0A
         makeAllL
@@ -3141,16 +3141,16 @@
 btree);%0A
-
 %0A       
@@ -3444,16 +3444,169 @@
 tNode);%0A
+%0A        // AnchorElement.getHref() and ImageElement.getSrc() both return the%0A        // absolute URI, so simply set them as the respective attributes.%0A%0A
         
@@ -3791,24 +3791,24 @@
 etItem(i));%0A
-
             
@@ -3842,21 +3842,276 @@
 );%0A        %7D
+%0A%0A        NodeList%3CElement%3E allImages = root.getElementsByTagName(%22IMG%22);%0A        for (int i = 0; i %3C allImages.getLength(); i++) %7B%0A            ImageElement image = ImageElement.as(allImages.getItem(i));%0A            image.setSrc(image.getSrc());%0A        %7D
 %0A    %7D%0A%7D%0A

make all images' sources absolute