package ro.isdc.wro.model.resource.processor.support;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.isdc.wro.util.WroUtil;


/**
 * Encapsulates the matcher creation for css backround url's detection. Useful to isolate unit tests.
 *
 * @author Alex Objelean
 * @created 20 Feb 2013
 * @since 1.6.3
 */
public class CssUrlInspector {
  private static final Logger LOG = LoggerFactory.getLogger(CssUrlInspector.class);
  private static final Pattern PATTERN = Pattern.compile(WroUtil.loadRegexpWithKey("cssUrlRewrite"));

  public final String findAndReplace(final String content, final ItemHandler handler) {
    final Matcher matcher = getMatcher(content);
    final StringBuffer sb = new StringBuffer();
    while (matcher.find()) {
      // Do not process @import statements
      /**
       * The url found inside @import statement should not be matched. This cannot be solved using regexp only because
       * of some limitations with negative look-around.
       */
      final String cssStatement = matcher.group();
      LOG.debug("Matched group: {}", cssStatement);
      if (!new CssImportInspector(cssStatement).containsImport()) {
        LOG.debug("No @import detected");
        final String originalDeclaration = getOriginalDeclaration(matcher);
        final String originalUrl = getOriginalUrl(matcher);
        LOG.debug("originalDeclaration: {}", originalDeclaration);
        LOG.debug("originalUrl: {}", originalUrl);

        Validate.notNull(originalUrl);
        matcher.appendReplacement(sb, handler.replace(originalDeclaration, originalUrl));
      }
    }
    matcher.appendTail(sb);
    return sb.toString();
  }

  /**
   * @return the {@link Matcher} for processed css content.
   */
  protected Matcher getMatcher(final String content) {
    return PATTERN.matcher(content);
  }

  /**
   * @param matcher
   *          the {@link Matcher} used to find url occurances.
   * @return the string representing entire css declaration containing the url.
   */
  protected String getOriginalDeclaration(final Matcher matcher) {
    return matcher.group(0);
  }

  /**
   * @param matcher
   *          the {@link Matcher} used to find url occurances.
   * @return the url found in css declaration.
   */
  protected String getOriginalUrl(final Matcher matcher) {
    /**
     * index of the group containing an url inside a declaration of this form:
     *
     * <pre>
     * body {
     *   filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/tabs/tabContent.png', sizingMethod='scale' );
     * }
     * </pre>
     *
     * or
     *
     * <pre>
     * @font-face {
     *   src: url(btn_icons.png);
     * }
     * </pre>
     */
    final String groupA = matcher.group(1);

    /**
     * index of the group containing an url inside a declaration of this form:
     *
     * <pre>
     * body {
     *     background: #B3B3B3 url(img.gif);
     *     color:red;
     * }
     * </pre>
     */
    final String originalUrl = groupA != null ? groupA : matcher.group(2);
    return originalUrl;
  }

  /**
   * The handler invoked for each found occurrence of url in parsed css.
   */
  public static interface ItemHandler {
    String replace(String originalDeclaration, String originalUrl);
  }
}
