// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.testframework.sm;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessage;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageParserCallback;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessagesParser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.text.ParseException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

public class ServiceMessageUtil {
  private static final Logger LOG = Logger.getInstance(ServiceMessageUtil.class);

  private ServiceMessageUtil() {
  }

  public static @Nullable ServiceMessage parse(@NotNull String text, boolean validateRequiredAttributes) {
    if (text.startsWith(ServiceMessage.SERVICE_MESSAGE_START) && text.endsWith(ServiceMessage.SERVICE_MESSAGE_END)) {
      ServiceMessagesParser parser = new ServiceMessagesParser();
      parser.setValidateRequiredAttributes(validateRequiredAttributes);
      AtomicReference<ServiceMessage> messageRef = new AtomicReference<>();
      AtomicBoolean exceptionOccurred = new AtomicBoolean(false);
      parser.parse(text, new ServiceMessageParserCallback() {
        @Override
        public void regularText(@NotNull String regularText) {
          LOG.error("Regular text encountered when parsing service message", text, regularText);
        }

        @Override
        public void serviceMessage(@NotNull ServiceMessage message) {
          if (messageRef.get() != null) {
            LOG.error("Another service message already parsed", text, messageRef.get().asString(), message.asString());
          }
          messageRef.set(message);
        }

        @Override
        public void parseException(@NotNull ParseException parseException, @NotNull String text1) {
          LOG.error("Failed to parse service message", parseException, text1);
          exceptionOccurred.set(true);
        }
      });
      if (!exceptionOccurred.get()) {
        return messageRef.get();
      }
    }
    return null;
  }
}

@@ -584,110 +584,8 @@
 ion;
-%0Aimport java.util.concurrent.atomic.AtomicBoolean;%0Aimport java.util.concurrent.atomic.AtomicReference;
 %0A%0Apu
@@ -1110,210 +1110,497 @@
     
-AtomicReference%3CServiceMessage%3E messageRef = new AtomicReference%3C%3E();%0A      AtomicBoolean exceptionOccurred = new AtomicBoolean(false);%0A      parser.parse(text, new ServiceMessageParserCallback() %7B%0A    
+MyServiceMessageParserCallback callback = new MyServiceMessageParserCallback(text);%0A      parser.parse(text, callback);%0A      return callback.getParsedMessage();%0A    %7D%0A    return null;%0A  %7D%0A%0A  private static class MyServiceMessageParserCallback implements ServiceMessageParserCallback %7B%0A    private @NotNull final String myText;%0A    private ServiceMessage myMessage;%0A    private boolean myParseFailed;%0A%0A    MyServiceMessageParserCallback(@NotNull String text) %7B%0A      myText = text;%0A    %7D%0A%0A
     
@@ -1601,36 +1601,32 @@
 %0A%0A    @Override%0A
-    
     public void 
@@ -1666,36 +1666,32 @@
 arText) %7B%0A      
- 
-   
 LOG.error(%22Regul
@@ -1741,17 +1741,19 @@
 ssage%22, 
-t
+myT
 ext, reg
@@ -1763,31 +1763,23 @@
 rText);%0A
-    
     %7D%0A%0A
-    
     @Ove
@@ -1776,36 +1776,32 @@
 %0A%0A    @Override%0A
-    
     public void 
@@ -1860,32 +1860,21 @@
     
-    
 if (m
+yM
 essage
-Ref.get()
  != 
@@ -1885,28 +1885,24 @@
 ) %7B%0A        
-    
 LOG.error(%22A
@@ -1945,30 +1945,25 @@
 d%22, 
-t
+myT
 ext, m
+yM
 essage
-Ref.get()
 .asS
@@ -1998,28 +1998,24 @@
 ;%0A      
-   
- 
 %7D%0A      
     mess
@@ -2010,56 +2010,40 @@
     
-   
- 
 m
+yM
 essage
-Ref.set(
+ = 
 message
-)
 ;%0A    
- 
-   
 %7D%0A%0A    
- 
-   
 @Ove
@@ -2048,20 +2048,16 @@
 verride%0A
-    
     publ
@@ -2135,21 +2135,30 @@
  String 
-t
+parseErrorT
 ext
-1
 ) %7B%0A    
@@ -2155,28 +2155,24 @@
 xt) %7B%0A      
- 
-   
 LOG.error(%22F
@@ -2224,13 +2224,22 @@
 on, 
-t
+parseErrorT
 ext
-1
 );%0A 
@@ -2247,95 +2247,90 @@
     
-   
- exceptionOccurred.set(
+myParseFailed = 
 true
-)
 ;%0A    
-    %7D%0A      %7D);%0A      if (!exceptionOccurred.get()
+%7D%0A%0A    public @Nullable ServiceMessage getParsedMessage(
 ) %7B%0A
@@ -2339,18 +2339,16 @@
     
-  
 return m
 essa
@@ -2347,55 +2347,46 @@
 rn m
-essageRef.get();%0A      %7D%0A    %7D%0A    return null;
+yParseFailed ? null : myMessage;%0A    %7D
 %0A  %7D

test runner: get rid of Atomic* classes to make code clearer (IDEA-CR-67149)