
/**
* 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.manifoldcf.agents.transformation.htmlextractor;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.apache.manifoldcf.crawler.system.Logging;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.nodes.Document.OutputSettings;
import org.jsoup.nodes.Entities.EscapeMode;
import org.jsoup.parser.Parser;
import org.jsoup.safety.Whitelist;

public class JsoupProcessing {




  public static Hashtable<String,String> extractTextAndMetadataHtmlDocument(InputStream streamDoc,String whitelist,List<String> blacklist, boolean stripHtml) throws IOException{
    Document doc = Jsoup.parse(streamDoc, "UTF-8", "");
    doc.outputSettings().escapeMode(EscapeMode.xhtml);
    Hashtable<String,String> metadata = new Hashtable<String,String>();
    for(Element meta : doc.select("meta")) {
      Logging.connectors.debug("Name: " + meta.attr("name") + " - Content: " + meta.attr("content"));
      metadata.put(meta.attr("name"), meta.attr("content"));
    }


    if (doc.select("title") != null){
      String title = doc.select("title").text();
      metadata.put("title", title);
    }

    Element element_keywords = doc.select("meta[name='keywords']").first();
    if (element_keywords != null) {
      String keywords = (element_keywords.attr("content"));
      metadata.put("keywords",keywords);
    }

    Element element_description = doc.select("meta[name=\"description\"]").first();
    if (element_description != null) {
      String description = (element_description.attr("content"));
      metadata.put("description",description);
    }

    Element element_author = doc.select("meta[name=\"author\"]").first();
    if (element_author != null) {
      String author = (element_author.attr("content"));
      metadata.put("author",author);
    }


    Element element_dcterms_subject = doc.select("meta[name=\"dcterms.subject\"]").first();
    if (element_dcterms_subject != null) {
      String dc_terms_subject = (element_dcterms_subject.attr("content"));
      metadata.put("dc_terms_subject",dc_terms_subject);
    }


    Element element_dcterms_title = doc.select("meta[name=\"dcterms.title\"]").first();
    if (element_dcterms_title != null) {
      String dc_terms_title = (element_dcterms_title.attr("content"));
      metadata.put("dc_terms_title",dc_terms_title);

    }

    Element element_dcterms_creator = doc.select("meta[name=\"dcterms.creator\"]").first();
    if (element_dcterms_creator != null) {
      String dc_terms_creator = (element_dcterms_creator.attr("content"));
      metadata.put("dc_terms_creator",dc_terms_creator);

    }

    Element element_dcterms_description = doc.select("meta[name=\"dcterms.description\"]").first();
    if (element_dcterms_description != null) {
      String dc_terms_description = (element_dcterms_description.attr("content"));
      metadata.put("dc_terms_description",dc_terms_description);

    }

    Element element_dcterms_publisher = doc.select("meta[name=\"dcterms.publisher\"]").first();
    if (element_dcterms_publisher != null) {
      String dc_terms_publisher = (element_dcterms_publisher.attr("content"));
      metadata.put("dc_terms_publisher",dc_terms_publisher);

    }

    Element element_dcterms_contributor = doc.select("meta[name=\"dcterms.contributor\"]").first();
    if (element_dcterms_contributor != null) {
      String dc_terms_contributor = (element_dcterms_contributor.attr("content"));
      metadata.put("dc_terms_contributor",dc_terms_contributor);

    }

    Element element_dcterms_date = doc.select("meta[name=\"dcterms.date\"]").first();
    if (element_dcterms_date != null) {
      String dc_terms_date = (element_dcterms_date.attr("content"));
      metadata.put("dc_terms_date",dc_terms_date);

    }

    Element element_dcterms_type = doc.select("meta[name=\"dcterms.type\"]").first();
    if (element_dcterms_type != null) {
      String dc_terms_type = (element_dcterms_type.attr("content"));
      metadata.put("dc_terms_type",dc_terms_type);

    }

    Element element_dcterms_format = doc.select("meta[name=\"dcterms.format\"]").first();
    if (element_dcterms_format != null) {
      String dc_terms_format = (element_dcterms_format.attr("content"));
      metadata.put("dc_terms_format",dc_terms_format);

    }

    Element element_dcterms_language = doc.select("meta[name=\"dcterms.language\"]").first();
    if (element_dcterms_language != null) {
      String dc_terms_language = (element_dcterms_language.attr("content"));
      metadata.put("dc_terms_language",dc_terms_language);

    }

    Element element_dcterms_identifier = doc.select("meta[name=\"dcterms.identifier\"]").first();
    if (element_dcterms_identifier != null) {
      String dc_terms_identifier = (element_dcterms_identifier.attr("content"));
      metadata.put("dc_terms_identifier",dc_terms_identifier);
    }


    Element docToKeep = doc.body();
    String finalDoc ;

    // Englobing Tag
    if (whitelist!="body"){
      docToKeep = doc.select(whitelist).first();
      // fallback to body tag if the tag chosen is not present in the page
      if (doc.select(whitelist).size() == 0) {
        docToKeep = doc.select("body").first();
      }
    }



    // Blacklist
    if (blacklist != null){
      for (int i=0; i< blacklist.size();i++){
        docToKeep.select(blacklist.get(i)).remove();
      }
    }

    if (stripHtml) {
      finalDoc = Jsoup.clean(docToKeep.html(),"",Whitelist.none(),new OutputSettings().prettyPrint(false));
    }
    else {
      finalDoc = Jsoup.clean(docToKeep.html(),Whitelist.relaxed());
    }
    // Jsoup escapes entities (eg '&' becomes '&amp;'), we don't want that as the extracted text must remain as it is, so unescape them 
    finalDoc = Parser.unescapeEntities(finalDoc, true);
    metadata.put("extractedDoc",finalDoc);

    return metadata;
  }

}