// Copyright (c) 2011, Mike Samuel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the OWASP nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package org.owasp.html;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * Sits between the HTML parser, and then policy, and the renderer so that it
 * can report dropped elements and attributes to an {@link HtmlChangeListener}.
 *
 * <pre>
 * HtmlChangeReporter&lt;T&gt; hcr = new HtmlChangeReporter&lt;T&gt;(
 *   renderer, htmlChangeListener, context);
 * hcr.setPolicy(policyFactory.apply(hcr.getWrappedRenderer()));
 * HtmlSanitizer.sanitize(html, hcr.getWrappedPolicy());
 * </pre>
 *
 * The renderer receives events from the policy unchanged, but the reporter
 * notices differences between the events from the lexer and those from the
 * policy.
 *
 * @param <T> The type of context value passed to the
 */
public final class HtmlChangeReporter<T> {
  private final OutputChannel output;
  private final InputChannel<T> input;

  public HtmlChangeReporter(
      HtmlStreamEventReceiver renderer,
      HtmlChangeListener<? super T> listener, @Nullable T context) {
    this.output = new OutputChannel(renderer);
    this.input = new InputChannel<T>(output, listener, context);
  }

  /**
   * Associates an input channel.  {@code this} receives events and forwards
   * them to input.
   */
  public void setPolicy(HtmlSanitizer.Policy policy) {
    this.input.policy = policy;
  }

  public HtmlStreamEventReceiver getWrappedRenderer() { return output; }

  public HtmlSanitizer.Policy getWrappedPolicy() { return input; }

  private static final class InputChannel<T> implements HtmlSanitizer.Policy {
    HtmlStreamEventReceiver policy;
    final OutputChannel output;
    final T context;
    final HtmlChangeListener<? super T> listener;

    InputChannel(
        OutputChannel output, HtmlChangeListener<? super T> listener,
        @Nullable T context) {
      this.output = output;
      this.context = context;
      this.listener = listener;
    }

    public void openDocument() {
      policy.openDocument();
    }

    public void closeDocument() {
      policy.closeDocument();
    }

    public void openTag(String elementName, List<String> attrs) {
      output.expectedElementName = elementName;
      output.expectedAttrNames.clear();
      for (int i = 0, n = attrs.size(); i < n; i += 2) {
        output.expectedAttrNames.add(attrs.get(i));
      }
      policy.openTag(elementName, attrs);
      {
        // Gather the notification details to avoid any problems with the
        // listener re-entering the stream event receiver.  This shouldn't
        // occur, but if it does it will be a source of subtle confusing bugs.
        String discardedElementName = output.expectedElementName;
        output.expectedElementName = null;
        int nExpected = output.expectedAttrNames.size();
        String[] discardedAttrNames =
            nExpected != 0 && discardedElementName == null
            ? output.expectedAttrNames.toArray(new String[nExpected])
            : ZERO_STRINGS;
        output.expectedAttrNames.clear();
        // Dispatch notifications to the listener.
        if (discardedElementName != null) {
          listener.discardedTag(context, discardedElementName);
        }
        if (discardedAttrNames.length != 0) {
          listener.discardedAttributes(
              context, elementName, discardedAttrNames);
        }
      }
    }

    public void closeTag(String elementName) {
      policy.closeTag(elementName);
    }

    public void text(String textChunk) {
      policy.text(textChunk);
    }
  }

  private static final class OutputChannel implements HtmlStreamEventReceiver {
    private final HtmlStreamEventReceiver renderer;
    String expectedElementName;
    Set<String> expectedAttrNames = new LinkedHashSet<String>();

    OutputChannel(HtmlStreamEventReceiver renderer) {
      this.renderer = renderer;
    }

    public void openDocument() {
      renderer.openDocument();
    }

    public void closeDocument() {
      renderer.closeDocument();
    }

    public void openTag(String elementName, List<String> attrs) {
      if (elementName.equals(expectedElementName)) {
        expectedElementName = null;
      }
      for (int i = 0, n = attrs.size(); i < n; i += 2) {
        expectedAttrNames.remove(attrs.get(i));
      }
      renderer.openTag(elementName, attrs);
    }

    public void closeTag(String elementName) {
      renderer.closeTag(elementName);
    }

    public void text(String text) {
      renderer.text(text);
    }
  }

  private static final String[] ZERO_STRINGS = new String[0];
}
