/*
 * #%L
 * wcm.io
 * %%
 * Copyright (C) 2019 wcm.io
 * %%
 * Licensed 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.
 * #L%
 */
package io.wcm.qa.glnm.sampling.htmlcleaner;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.HtmlSerializer;
import org.htmlcleaner.SimpleHtmlSerializer;
import org.htmlcleaner.TagNode;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;

import io.wcm.qa.glnm.sampling.jsoup.JsoupRawStringSampler;

/**
 * Uses HTML cleaner to tidy up HTML samples fetched with {@link Jsoup}.
 */
public class HtmlCleanerSampler extends JsoupRawStringSampler {

  private CleanerProperties htmlCleanerProperties;

  private HtmlSerializer htmlSerializer;
  private boolean sortCssClasses = true;

  /**
   * @param url to sample from
   */
  public HtmlCleanerSampler(String url) {
    this(url, new CleanerProperties());
  }

  /**
   * @param url to sample from
   * @param cleanerProperties properties to configure {@link HtmlCleaner}
   */
  public HtmlCleanerSampler(String url, CleanerProperties cleanerProperties) {
    super(url);
    setBodyOnly(false);
    setHtmlCleanerProperties(cleanerProperties);
  }

  public CleanerProperties getHtmlCleanerProperties() {
    return htmlCleanerProperties;
  }

  /**
   * @return serializer to use for HTML string serialization
   */
  public HtmlSerializer getHtmlSerializer() {
    if (htmlSerializer == null) {
      htmlSerializer = new SimpleHtmlSerializer(getHtmlCleanerProperties());
    }
    return htmlSerializer;
  }

  public boolean isSortCssClasses() {
    return sortCssClasses;
  }

  public void setHtmlCleanerProperties(CleanerProperties htmlCleanerProperties) {
    this.htmlCleanerProperties = htmlCleanerProperties;
  }

  public void setHtmlSerializer(HtmlSerializer htmlSerializer) {
    this.htmlSerializer = htmlSerializer;
  }

  public void setSortCssClasses(boolean sortCssClasses) {
    this.sortCssClasses = sortCssClasses;
  }

  private HtmlCleaner getHtmlCleaner() {
    HtmlCleaner htmlCleaner = new HtmlCleaner(getHtmlCleanerProperties());
    return htmlCleaner;
  }

  @Override
  protected String extractValueFromElement(Element element) {
    String jsoupHtml = super.extractValueFromElement(element);
    HtmlCleaner htmlCleaner = getHtmlCleaner();
    TagNode cleanedHtml = htmlCleaner.clean(jsoupHtml);
    if (isSortCssClasses()) {
      cleanedHtml.traverse(new CssClassSorter());
    }
    return getHtmlSerializer().getAsString(cleanedHtml);
  }

}

@@ -667,16 +667,68 @@
 eaner;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.List;%0A%0A
 import o
@@ -761,16 +761,16 @@
 erties;%0A
-
 import o
@@ -913,16 +913,55 @@
 agNode;%0A
+import org.htmlcleaner.TagNodeVisitor;%0A
 import o
@@ -1005,24 +1005,92 @@
 s.Element;%0A%0A
+import io.wcm.qa.glnm.sampling.htmlcleaner.visitors.CssClassSorter;%0A
 import io.wc
@@ -1377,16 +1377,17 @@
 alizer;%0A
+%0A
   privat
@@ -1420,16 +1420,92 @@
  true;%0A%0A
+  private List%3CTagNodeVisitor%3E visitors = new ArrayList%3CTagNodeVisitor%3E();%0A%0A
   /**%0A  
@@ -1912,24 +1912,158 @@
 ties);%0A  %7D%0A%0A
+  /**%0A   * @param visitor to clean HTML%0A   */%0A  public void addVisitor(TagNodeVisitor visitor) %7B%0A    getVisitors().add(visitor);%0A  %7D%0A%0A
   public Cle
@@ -3323,59 +3323,228 @@
     
-return getHtmlSerializer().getAsString(cleanedHtml)
+for (TagNodeVisitor visitor : getVisitors()) %7B%0A      cleanedHtml.traverse(visitor);%0A    %7D%0A    return getHtmlSerializer().getAsString(cleanedHtml);%0A  %7D%0A%0A  protected List%3CTagNodeVisitor%3E getVisitors() %7B%0A    return visitors
 ;%0A  

add visitors to API