// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

/** Interface for receiving String resource. */
@KeepForSubclassing
public interface StringConsumer extends Finishable {

  /**
   * Callback to receive part of a string resource.
   *
   * <p>The consumer is expected not to throw, but instead report any errors via the diagnostics
   * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown,
   * then the compiler guaranties to exit with an error.
   *
   * <p>Note: prior to the addition of 'finished' consumers could expect all content to be reported
   * in one call to accept. That is no longer guaranteed.
   *
   * @param string Part of the string resource.
   * @param handler Diagnostics handler for reporting.
   */
  void accept(String string, DiagnosticsHandler handler);

  static EmptyConsumer emptyConsumer() {
    return EmptyConsumer.EMPTY_CONSUMER;
  }

  /** Empty consumer to request the production of the resource but ignore its value. */
  @Keep
  class EmptyConsumer implements StringConsumer {

    private static final EmptyConsumer EMPTY_CONSUMER = new EmptyConsumer();

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      // Ignore content.
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      // No content so, nothing to do.
    }
  }

  /** Forwarding consumer to delegate to an optional existing consumer. */
  @Keep
  class ForwardingConsumer implements StringConsumer {

    private final StringConsumer consumer;

    /** @param consumer Consumer to forward to, if null, nothing will be forwarded. */
    public ForwardingConsumer(StringConsumer consumer) {
      this.consumer = consumer;
    }

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      if (consumer != null) {
        consumer.accept(string, handler);
      }
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      if (consumer != null) {
        consumer.finished(handler);
      }
    }
  }

  /** File consumer to write contents to a file-system file. */
  @Keep // TODO(b/121121779) Consider deprecating the R8 provided file writing.
  class FileConsumer extends ForwardingConsumer {

    private final Path outputPath;
    private Charset encoding = StandardCharsets.UTF_8;
    private WriterConsumer delegate = null;
    private boolean failedToCreateDelegate = false;

    /** Consumer that writes to {@param outputPath}. */
    public FileConsumer(Path outputPath) {
      this(outputPath, null);
    }

    /** Consumer that forwards to {@param consumer} and also writes to {@param outputPath}. */
    public FileConsumer(Path outputPath, StringConsumer consumer) {
      super(consumer);
      this.outputPath = outputPath;
    }

    /** Get the output path that the consumer will write to. */
    public Path getOutputPath() {
      return outputPath;
    }

    /** Set the output encoding. Defaults to UTF8. */
    public void setEncoding(Charset encoding) {
      assert encoding != null;
      if (delegate != null) {
        throw new IllegalStateException("Invalid call to set encoding after file stream is opened");
      }
      this.encoding = encoding;
    }

    /** Get the output encoding. Defaults to UTF8. */
    public Charset getEncoding() {
      return encoding;
    }

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      super.accept(string, handler);
      if (failedToCreateDelegate) {
        return;
      }
      ensureDelegate(handler);
      if (delegate != null) {
        delegate.accept(string, handler);
      }
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      super.finished(handler);
      if (failedToCreateDelegate) {
        return;
      }
      ensureDelegate(handler);
      if (delegate != null) {
        delegate.finished(handler);
        delegate = null;
      }
    }

    private void ensureDelegate(DiagnosticsHandler handler) {
      if (delegate != null) {
        return;
      }
      PathOrigin origin = new PathOrigin(outputPath);
      try {
        Path parent = outputPath.getParent();
        if (parent != null && !parent.toFile().exists()) {
          Files.createDirectories(parent);
        }
        delegate = new WriterConsumer(origin, Files.newBufferedWriter(outputPath, encoding));
      } catch (IOException e) {
        failedToCreateDelegate = true;
        handler.error(new ExceptionDiagnostic(e, origin));
      }
    }
  }

  /**
   * String consumer to write contents to a Writer.
   *
   * <p>Note: The writer is closed when the consumer receives its 'finished' callback.
   */
  class WriterConsumer extends ForwardingConsumer {

    private final Origin origin;
    private Writer writer;

    /** Consumer that writes to {@param writer}. */
    public WriterConsumer(Origin origin, Writer writer) {
      this(origin, writer, null);
    }

    /** Consumer that forwards to {@param consumer} and also writes to {@param writer}. */
    public WriterConsumer(Origin origin, Writer writer, StringConsumer consumer) {
      super(consumer);
      this.origin = origin;
      this.writer = writer;
    }

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      super.accept(string, handler);
      try {
        writer.write(string);
      } catch (IOException e) {
        handler.error(new ExceptionDiagnostic(e, origin));
      }
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      super.finished(handler);
      try {
        writer.close();
      } catch (IOException e) {
        handler.error(new ExceptionDiagnostic(e, origin));
      }
    }
  }
}
