/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.rt.ant.execution;

import com.intellij.rt.execution.junit.segments.PacketWriter;
import com.intellij.rt.execution.junit.segments.SegmentedOutputStream;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;

public final class IdeaAntLogger2 extends DefaultLogger {
  static SegmentedOutputStream ourErr;
  public static final char MESSAGE_CONTENT = 'M';
  public static final char EXCEPTION_CONTENT = 'X';
  public static final char INPUT_REQUEST = 'I';
  public static final char BUILD_END = 'b';
  public static final char BUILD = 'B';
  public static final char TARGET = 'G';
  public static final char TARGET_END = 'g';
  public static final char TASK = 'T';
  public static final char TASK_END = 't';
  public static final char MESSAGE = 'M';
  public static final char ERROR = 'E';
  public static final char EXCEPTION = 'X';
  public static final char EXCEPTION_LINE_SEPARATOR = 0;

  /**
   * @noinspection HardCodedStringLiteral
   */
  public static final String OUTPUT_PREFIX = "IDEA_ANT_INTEGRATION";

  private final Priority myMessagePriority = new MessagePriority();
  private final Priority myTargetPriority = new StatePriority(Project.MSG_INFO);
  private final Priority myTaskPriority = new StatePriority(Project.MSG_INFO);
  private final Priority myAlwaysSend = new Priority() {
    public void setPriority(int level) {}

    protected boolean shouldSend(int priority) {
      return true;
    }
  };

  public IdeaAntLogger2() {
    guardStreams();
  }

  public synchronized void setMessageOutputLevel(int level) {
    super.setMessageOutputLevel(level);
    myMessagePriority.setPriority(level);
    myTargetPriority.setPriority(level);
    myTaskPriority.setPriority(level);
    myAlwaysSend.setPriority(level);
  }

  public synchronized void buildStarted(BuildEvent event) {
    myAlwaysSend.sendMessage(BUILD, event.getPriority(), "");
  }

  public synchronized void buildFinished(BuildEvent event) {
    myAlwaysSend.sendMessage(BUILD_END, event.getPriority(), event.getException());
  }

  public synchronized void targetStarted(BuildEvent event) {
    myTargetPriority.sendMessage(TARGET, event.getPriority(), event.getTarget().getName());
  }

  public synchronized void targetFinished(BuildEvent event) {
    sendException(event, true);
    myTargetPriority.sendMessage(TARGET_END, event.getPriority(), event.getException());
  }

  public synchronized void taskStarted(BuildEvent event) {
    myTaskPriority.sendMessage(TASK, event.getPriority(), event.getTask().getTaskName());
  }

  public synchronized void taskFinished(BuildEvent event) {
    sendException(event, true);
    myTaskPriority.sendMessage(TASK_END, event.getPriority(), event.getException());
  }

  public synchronized void messageLogged(BuildEvent event) {
    final boolean failOnError = isFailOnError(event);
    if (sendException(event, failOnError)) {
      return;
    }

    int priority = event.getPriority();
    if (priority == Project.MSG_ERR && !failOnError) {
      // some ant tasks (like Copy) with 'failOnError' attribute set to 'false'
      // send warnings with priority level = Project.MSG_ERR
      // this heuristic corrects the priority level, so that IDEA considers the message not as an error but as a warning
      priority = Project.MSG_WARN;
    }

    final String message = event.getMessage();

    if (priority == Project.MSG_ERR) {
      myMessagePriority.sendMessage(ERROR, priority, message);
    }
    else {
      myMessagePriority.sendMessage(MESSAGE, priority, message);
    }
  }

  private static boolean isFailOnError(BuildEvent event) {
    final Task task = event.getTask();
    if (task != null) {
      try {
        final Field field = task.getClass().getDeclaredField("failonerror");
        field.setAccessible(true);
        return !Boolean.FALSE.equals(field.get(task));
      }
      catch (Exception ignored) {
      }
    }
    return true; // default value
  }

  private boolean sendException(BuildEvent event, boolean isFailOnError) {
    Throwable exception = event.getException();
    if (exception != null) {
      if (isFailOnError) {
        myAlwaysSend.sendMessage(EXCEPTION, event.getPriority(), exception);
        return true;
      }
      myMessagePriority.sendMessage(MESSAGE, Project.MSG_WARN, exception.getMessage());
    }
    return false;
  }

  public static void guardStreams() {
    if (ourErr != null) {
      return;
    }
    PrintStream err = System.err;
    ourErr = new SegmentedOutputStream(err);
    System.setErr(new PrintStream(ourErr));
    ourErr.sendStart();
  }

  private void send(PacketWriter packet) {
    packet.sendThrough(ourErr);
  }

  private PacketWriter createPacket(char id, int priority) {
    PacketWriter packet = PacketFactory.ourInstance.createPacket(id);
    packet.appendLong(priority);
    return packet;
  }

  private abstract class Priority {
    protected void peformSendMessage(char id, int priority, String text) {
      PacketWriter packet = createPacket(id, priority);
      packet.appendChar(MESSAGE_CONTENT);
      packet.appendLimitedString(text);
      send(packet);
    }

    protected void peformSendMessage(char id, int priority, Throwable throwable) {
      if (throwable != null) {
        PacketWriter packet = createPacket(id, priority);
        StringWriter stackTrace = new StringWriter();
        throwable.printStackTrace(new PrintWriter(stackTrace));
        packet.appendChar(EXCEPTION_CONTENT);
        packet.appendLimitedString(stackTrace.toString());
        send(packet);
      } else {
        peformSendMessage(id, priority, "");
      }
    }

    public void sendMessage(char id, int priority, String text) {
      if (shouldSend(priority)) peformSendMessage(id, priority, text);
    }

    public void sendMessage(char id, int priority, Throwable throwable) {
      if (shouldSend(priority)) peformSendMessage(id, priority, throwable);
    }

    public abstract void setPriority(int level);
    protected abstract boolean shouldSend(int priority);
  }

  private class MessagePriority extends Priority {
    private int myPriority = Project.MSG_ERR;

    public void setPriority(int level) {
      myPriority = level;
    }

    protected boolean shouldSend(int priority) {
      return priority <= myPriority;
    }
  }

  private class StatePriority extends Priority {
    private boolean myEnabled = true;
    private final int myMinLevel;

    public StatePriority(int minLevel) {
      myMinLevel = minLevel;
    }

    public void setPriority(int level) {
      myEnabled = myMinLevel <= level;
    }

    protected boolean shouldSend(int priority) {
      return myEnabled;
    }
  }
}
