// Copyright (C) 2015 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.manager;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;

public class TokenReplaceOutputStream extends ServletOutputStream {

  private final byte[] token;

  private final byte[] replace;

  private final ByteArrayOutputStream outBuff;

  private final HttpServletResponse resp;

  private final int outLen;

  public TokenReplaceOutputStream(
      HttpServletResponse resp, int contentLength, byte[] token, byte[] replace) {
    this.resp = resp;
    this.outLen = contentLength;
    this.token = token;
    this.replace = replace;
    this.outBuff = new ByteArrayOutputStream(contentLength);
  }

  @Override
  public void write(int b) throws IOException {
    outBuff.write(b);
  }

  @Override
  public void flush() throws IOException {
    if (outBuff.size() < outLen) {
      return;
    }

    byte[] outData = outBuff.toByteArray();
    byte[] cmp = new byte[token.length];
    ByteArrayOutputStream convertedData = new ByteArrayOutputStream(outData.length);

    for (int i = 0; i < outData.length; i++) {
      byte b = outData[i];
      if (b != token[0] || (outData.length - i) < token.length) {
        convertedData.write(outData, i, 1);
        continue;
      }

      System.arraycopy(outData, i, cmp, 0, token.length);
      if (Arrays.equals(cmp, token)) {
        convertedData.write(replace);
        i += token.length - 1;
      }
    }

    resp.setHeader("Content-Length", "" + convertedData.size());

    ServletOutputStream out = resp.getOutputStream();
    out.write(convertedData.toByteArray());
    out.flush();
  }

  @Override
  public void close() throws IOException {
    flush();
  }

  @Override
  public void write(byte[] b) throws IOException {
    outBuff.write(b);
    flush();
  }

  @Override
  public void write(byte[] b, int off, int len) throws IOException {
    outBuff.write(b, off, len);
    flush();
  }

  @Override
  public void setWriteListener(WriteListener writeListener) {}

  @Override
  public boolean isReady() {
    return true;
  }
}
