/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You 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 org.apache.poi.hmef;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LZWDecompresser;
import org.apache.poi.util.LittleEndian;


/**
 * Within a {@link HMEFMessage}, the content is often
 *  stored in as RTF, but LZW compressed. This class
 *  handles decompressing it for you.
 */
public final class CompressedRTF extends LZWDecompresser {
   // github-77: mutable static fields could be changed by malicious code or by accident.
   // These byte arrays should be package protected.
   /*package*/ static final byte[] COMPRESSED_SIGNATURE =
      new byte[] { (byte)'L', (byte)'Z', (byte)'F', (byte)'u' };
   /*package*/ static final byte[] UNCOMPRESSED_SIGNATURE =
      new byte[] { (byte)'M', (byte)'E', (byte)'L', (byte)'A' };
   public static final int COMPRESSED_SIGNATURE_INT =
      LittleEndian.getInt(COMPRESSED_SIGNATURE);
   public static final int UNCOMPRESSED_SIGNATURE_INT =
      LittleEndian.getInt(UNCOMPRESSED_SIGNATURE);

   // The 4096 byte LZW dictionary is pre-loaded with some common
   //  RTF fragments. These come from RTFLIB32.LIB, which ships
   //  with older versions of Visual Studio or the EDK
   public static final String LZW_RTF_PRELOAD =
      "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss " +
      "\\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier" +
      "{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx";

   private int compressedSize;
   private int decompressedSize;

   public CompressedRTF() {
      // Out flag has the normal meaning
      // Length wise, we're 2 longer than we say, so the max len is 18
      // Endian wise, we're big endian, so 0x1234 is pos 0x123
      super(true, 2, true);
   }

   /**
    * Decompresses the whole of the compressed RTF
    *  stream, outputting the resulting RTF bytes.
    * Note - will decompress any padding at the end of
    *  the input, if present, use {@link #getDeCompressedSize()}
    *  if you need to know how much of the result is
    *  real. (Padding may be up to 7 bytes).
    */
   public void decompress(InputStream src, OutputStream res) throws IOException {
      // Validate the header on the front of the RTF
      compressedSize = LittleEndian.readInt(src);
      decompressedSize = LittleEndian.readInt(src);
      int compressionType = LittleEndian.readInt(src);
      /* int dataCRC = */ LittleEndian.readInt(src);

      // TODO - Handle CRC checking on the output side

      // Do we need to do anything?
      if(compressionType == UNCOMPRESSED_SIGNATURE_INT) {
         // Nope, nothing fancy to do
         IOUtils.copy(src, res);
      } else if(compressionType == COMPRESSED_SIGNATURE_INT) {
         // We need to decompress it below
      } else {
         throw new IllegalArgumentException("Invalid compression signature " + compressionType);
      }

      // Have it processed
      super.decompress(src, res);
   }

   /**
    * Returns how big the compressed version was.
    */
   public int getCompressedSize() {
      // Return the size less the header
      return compressedSize - 12;
   }

   /**
    * Returns how big the decompressed version was.
    */
   public int getDeCompressedSize() {
      return decompressedSize;
   }

   /**
    * We use regular dictionary offsets, so no
    *  need to change anything
    */
   @Override
   protected int adjustDictionaryOffset(int offset) {
      return offset;
   }

   @Override
   protected int populateDictionary(byte[] dict) {
     // Copy in the RTF constants
     byte[] preload = LZW_RTF_PRELOAD.getBytes(StandardCharsets.US_ASCII);
     System.arraycopy(preload, 0, dict, 0, preload.length);

     // Start adding new codes after the constants
     return preload.length;
   }
}
