package io.wcm.qa.glnm.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.wcm.qa.glnm.reporting.GaleniumReportUtil;
/**
 * <p>
 * MatcherAspect class.
 * </p>
 *
 * @since 5.0.0
 */
@Aspect("perthis(execution(* *..*.matches(..)))")
public class MatcherAspect {

  private static final Logger LOG = LoggerFactory.getLogger(MatcherAspect.class);
  private String startStepUuid;

  /**
   * <p>
   * hamcrestMatcherMatch.
   * </p>
   */
  @Pointcut("execution(boolean org.hamcrest.Matcher.matches(..))")
  public void hamcrestMatcherMatch() {
    // pointcut body, should be empty
  }

  /**
   * <p>
   * startMatch.
   * </p>
   *
   * @param joinPoint a {@link org.aspectj.lang.JoinPoint} object.
   */
  @Before("execution(boolean org.hamcrest.Matcher.matches(..))")
  public void startMatching(final JoinPoint joinPoint) {
    if (LOG.isTraceEnabled()) {
      LOG.trace("before: " + joinPoint.getSignature().toLongString());
    }
    startStepUuid = GaleniumReportUtil.startStep("matching");
  }

  /**
   * <p>failedMatching.</p>
   *
   * @param joinPoint a {@link org.aspectj.lang.JoinPoint} object.
   * @param e a {@link java.lang.Throwable} object.
   */
  @AfterThrowing(pointcut = "execution(boolean org.hamcrest.Matcher.matches(..))", throwing = "e")
  public void failedMatching(final JoinPoint joinPoint, final Throwable e) {
    if (LOG.isTraceEnabled()) {
      LOG.trace("failed: " + joinPoint.getSignature().toLongString());
    }
    StringDescription stringDescription = new StringDescription();
    Matcher target = (Matcher)joinPoint.getTarget();
    target.describeTo(stringDescription);
    stringDescription.appendText(e.getMessage());

  }

  /**
   * <p>doneMatching.</p>
   *
   * @param joinPoint a {@link org.aspectj.lang.JoinPoint} object.
   * @param result a boolean.
   */
  @AfterReturning(pointcut = "execution(boolean org.hamcrest.Matcher.matches(..))", returning = "result")
  public void doneMatching(final JoinPoint joinPoint, boolean result) {
    if (LOG.isTraceEnabled()) {
      LOG.trace("done: " + joinPoint.getSignature().toLongString());
    }
    Matcher target = (Matcher)joinPoint.getTarget();
    StringDescription stringDescription = new StringDescription();
    target.describeTo(stringDescription);
    if (result) {
      GaleniumReportUtil.updateStepName(startStepUuid, stringDescription.toString());
      GaleniumReportUtil.passStep(startStepUuid);
      GaleniumReportUtil.stopStep();
    }
    else {
      stringDescription.appendText("\n");
      target.describeMismatch(joinPoint.getArgs()[0], stringDescription);
      GaleniumReportUtil.updateStepName(startStepUuid, stringDescription.toString());
      GaleniumReportUtil.failStep(startStepUuid);
      GaleniumReportUtil.stopStep();
    }
  }

}

@@ -293,16 +293,53 @@
 intcut;%0A
+import org.hamcrest.BaseDescription;%0A
 import o
@@ -2490,38 +2490,39 @@
   %7D%0A    Matcher 
-target
+matcher
  = (Matcher)join
@@ -2548,133 +2548,440 @@
     
-StringDescription stringDescription = new StringDescription();%0A    target.describeTo(stringDescription);%0A    if (result) %7B%0A  
+if (result) %7B%0A      passStep(matcher);%0A    %7D%0A    else %7B%0A      failStep(joinPoint, matcher);%0A    %7D%0A  %7D%0A%0A  private void failStep(final JoinPoint joinPoint, Matcher matcher) %7B%0A    BaseDescription description = descriptionFor(matcher);%0A    description%0A        .appendText(System.lineSeparator())%0A        .appendText(%22     but: %22);%0A    Object matchedItem = joinPoint.getArgs()%5B0%5D;%0A    matcher.describeMismatch(matchedItem, description);%0A
     
@@ -3021,39 +3021,33 @@
 (startStepUuid, 
-stringD
+d
 escription.toStr
@@ -3050,34 +3050,32 @@
 oString());%0A    
-  
 GaleniumReportUt
@@ -3077,20 +3077,20 @@
 ortUtil.
-pass
+fail
 Step(sta
@@ -3094,34 +3094,32 @@
 startStepUuid);%0A
-  
     GaleniumRepo
@@ -3141,143 +3141,56 @@
 ();%0A
-  
   %7D%0A
-    else %7B%0A      stringDescription.appendText(%22%5Cn%22);%0A      target.describeMismatch(joinPoint.getArgs()%5B0%5D, stringDescription);%0A  
+%0A  private void passStep(Matcher matcher) %7B%0A
     
@@ -3238,23 +3238,17 @@
 epUuid, 
-stringD
+d
 escripti
@@ -3241,32 +3241,44 @@
 uid, description
+For(matcher)
 .toString());%0A  
@@ -3275,18 +3275,16 @@
 ing());%0A
-  
     Gale
@@ -3290,36 +3290,36 @@
 eniumReportUtil.
-fail
+pass
 Step(startStepUu
@@ -3327,18 +3327,16 @@
 d);%0A    
- 
- 
 Galenium
@@ -3360,19 +3360,255 @@
 ep();%0A  
-  %7D
+%7D%0A%0A  private StringDescription descriptionFor(Matcher matcher) %7B%0A    StringDescription description = new StringDescription();%0A    description%0A        .appendText(%22Expected: %22)%0A        .appendDescriptionOf(matcher);%0A    return description;
 %0A  %7D%0A%0A
+%0A
 %7D%0A

improve step descriptions