/* sbt -- Simple Build Tool
 * Copyright 2008, 2009 Mark Harrah
 */
package xsbt;

import java.util.Optional;

import xsbti.Position;
import xsbti.Severity;

import dotty.tools.*;
import dotty.tools.dotc.*;
import dotty.tools.dotc.interfaces.Diagnostic;
import dotty.tools.dotc.util.SourceFile;
import dotty.tools.dotc.util.SourcePosition;
import dotty.tools.dotc.reporting.*;
import dotty.tools.dotc.reporting.diagnostic.Message;
import dotty.tools.dotc.reporting.diagnostic.MessageContainer;
import dotty.tools.dotc.reporting.diagnostic.messages;
import dotty.tools.dotc.core.Contexts.*;

import static dotty.tools.dotc.reporting.diagnostic.MessageContainer.*;

final public class DelegatingReporter extends AbstractReporter {
  private final xsbti.Reporter delegate;

  private static final Position noPosition = new Position() {
    public Optional<java.io.File> sourceFile() {
      return Optional.empty();
    }
    public Optional<String> sourcePath() {
      return Optional.empty();
    }
    public Optional<Integer> line() {
      return Optional.empty();
    }
    public String lineContent() {
      return "";
    }
    public Optional<Integer> offset() {
      return Optional.empty();
    }
    public Optional<Integer> pointer() {
      return Optional.empty();
    }
    public Optional<String> pointerSpace() {
      return Optional.empty();
    }
  };

  public DelegatingReporter(xsbti.Reporter delegate) {
    super();
    this.delegate = delegate;
  }

  @Override
  public void printSummary(Context ctx) {
    delegate.printSummary();
  }

  public void doReport(MessageContainer cont, Context ctx) {
    Severity severity;
    switch (cont.level()) {
      case Diagnostic.ERROR:
        severity = Severity.Error;
        break;
      case Diagnostic.WARNING:
        severity = Severity.Warn;
        break;
      case Diagnostic.INFO:
        severity = Severity.Info;
        break;
      default:
        throw new IllegalArgumentException("Bad diagnostic level: " + cont.level());
    }

    Position position;
    if (cont.pos().exists()) {
      SourcePosition pos = cont.pos();
      SourceFile src = pos.source();
      position = new Position() {
        public Optional<java.io.File> sourceFile() {
          return Optional.ofNullable(src.file().file());
        }
        public Optional<String> sourcePath() {
          return Optional.ofNullable(src.file().path());
        }
        public Optional<Integer> line() {
          int line = pos.line();
          if (line == -1) return Optional.empty();
          else return Optional.of(line);
        }
        public String lineContent() {
          String line = pos.lineContent();
          if (line.endsWith("\r\n"))
            return line.substring(0, line.length() - 2);
          else if (line.endsWith("\n") || line.endsWith("\u000c"))
            return line.substring(0, line.length() - 1);
          else
            return line;
        }
        public Optional<Integer> offset() {
          return Optional.of(pos.point());
        }
        public Optional<Integer> pointer() {
          return Optional.of(pos.point() - src.startOfLine(pos.point()));
        }
        public Optional<String> pointerSpace() {
          String lineContent = this.lineContent();
          int pointer = this.pointer().get();
          StringBuilder result = new StringBuilder();
          for (int i = 0; i < pointer; i++)
            result.append(lineContent.charAt(i) == '\t' ? '\t' : ' ');
          return Optional.of(result.toString());
        }
      };
    } else {
      position = noPosition;
    }

    Message message = cont.contained();
    StringBuilder rendered = new StringBuilder();
    rendered.append(messageAndPos(message, cont.pos(), diagnosticLevel(cont), ctx));
    boolean shouldExplain = new MessageContainer.MessageContext(ctx).shouldExplain(cont);
    if (shouldExplain && !message.explanation().isEmpty()) {
      rendered.append(explanation(message, ctx));
    }

    delegate.log(new Problem(position, message.msg(), severity, rendered.toString()));
  }
}

@@ -3081,32 +3081,91 @@
 r() %7B%0A          
+if (!src.exists()) return Optional.empty();%0A          else 
 return Optional.
@@ -3267,24 +3267,97 @@
 erSpace() %7B%0A
+          if (!src.exists()) return Optional.empty();%0A          else %7B%0A  
           St
@@ -3401,24 +3401,26 @@
 ;%0A          
+  
 int pointer 
@@ -3449,24 +3449,26 @@
 ;%0A          
+ 
+ 
 StringBuilde
@@ -3509,16 +3509,18 @@
         
+  
 for (int
@@ -3545,16 +3545,18 @@
 r; i++)%0A
+  
         
@@ -3620,32 +3620,34 @@
 ' ');%0A          
+  
 return Optional.
@@ -3665,24 +3665,36 @@
 oString());%0A
+          %7D%0A
         %7D%0A  

Return empty Optional for poiter with empty source