package com.codeborne.selenide.impl;

import com.codeborne.selenide.logevents.LogEvent;
import com.codeborne.selenide.logevents.LogEventListener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.codeborne.selenide.logevents.LogEvent.EventStatus.FAILED;

/**
 * EXPERIMENTAL
 * to be refactored soon
 * <p/>
 * Logs Selenide test steps and notifies all registered LogEventListener about it
 *
 * @since Selenide 2.16
 */
public class SelenideLogger {
  protected static ThreadLocal<List<LogEventListener>> listeners = new ThreadLocal<List<LogEventListener>>();

  public static void addListener(LogEventListener listener) {
    List<LogEventListener> list = listeners.get();
    if (list == null) {
      list = new ArrayList<>();
    }

    list.add(listener);
    listeners.set(list);
  }

  public static SelenideLog beginStep(String source, String methodName, Object... args) {
    return beginStep(source, readableMethodName(methodName) + "(" + readableArguments(args) + ")");
  }

  static String readableMethodName(String methodName) {
    return methodName.replaceAll("([A-Z])", " $1").toLowerCase();
  }

  static String readableArguments(Object... args) {
    return args == null ? "" :
        (args[0] instanceof Object[]) ? arrayToString((Object[]) args[0]) :
            arrayToString(args);
  }

  private static String arrayToString(Object[] args) {
    return args.length == 1 ? String.valueOf(args[0]) : Arrays.toString(args);
  }

  public static SelenideLog beginStep(String source, String subject) {
    return new SelenideLog(source, subject);
  }

  public static void commitStep(SelenideLog log, Throwable error) {
    log.setError(error);
    commitStep(log, FAILED);
  }
  
  public static void commitStep(SelenideLog log, LogEvent.EventStatus status) {
    log.setStatus(status);

    List<LogEventListener> listeners = getEventLoggerListeners();
    for (LogEventListener listener : listeners) {
      listener.onEvent(log);
    }
  }

  private static List<LogEventListener> getEventLoggerListeners() {
    if (listeners.get() == null) {
      listeners.set(new ArrayList<LogEventListener>());
    }
    return listeners.get();
  }

  /**
   * This method is dangerous because it clears ALL listeners (probably registered by others).
   * @deprecated use method removeListener(LogEventListener).
   */
  @Deprecated
  public static void clearListeners() {
    listeners.remove();
  }
  
  public static void removeListener(LogEventListener listener) {
    listeners.get().remove(listener);
    if (listeners.get().isEmpty()) {
      listeners.remove();
    }
  }
}

@@ -573,38 +573,16 @@
 adLocal%3C
-List%3CLogEventListener%3E
 %3E();%0A%0A  
@@ -2181,260 +2181,8 @@
 %0A  %7D
-%0A%0A  /**%0A   * This method is dangerous because it clears ALL listeners (probably registered by others).%0A   * @deprecated use method removeListener(LogEventListener).%0A   */%0A  @Deprecated%0A  public static void clearListeners() %7B%0A    listeners.remove();%0A  %7D
 %0A  %0A

remove deprecated method SelenideLogger.clearListeners()